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

WIP: Add support for categories. To fix #10 #323

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

christf
Copy link

@christf christf commented Sep 17, 2018

This adds categories to todoman.

  • implement setting --category multiple times
  • implement test for multiple categories
  • adjust table layout
  • allow to write to the new table structure
  • allow to edit the structure. Currently "aaaaa,bbbb" will be written as "a,a,a,a,a,,,b,b,b,b" when entered in the interactive editor. However it will be fine when specifying via clia.
  • allow to read from the new table structure
  • handle the strings, forming a list for the UI.
  • allow to filter tasks having one category
  • allow to filter tasks having multiple categories

Copy link
Member

@WhyNotHugo WhyNotHugo left a comment

Choose a reason for hiding this comment

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

As mentioned in #10:

Regarding the commas issue, it looks like using t.set_inline('category', ['foo','bar']) sets them properly (and also escapes commas INSIDE categories properly).

This probably needs some changes in TodoWritter.set_field (overriding the behavior for CATEGORIES).


I also think we might be able to use the multiple options feature here, so category names can actually contain commas (which would actually be escaped). This would slightly change usage to:

todo new --category foo --category bar Some description

I think this is slightly tidier than forcing people to comma-separate, what do you think about this?


Looking pretty good so far though, thanks!

tests/test_cli.py Show resolved Hide resolved
@penguineer
Copy link
Contributor

TodoWriter.set_field calls add on the vtodo. This is icalendar.Component.add, with the relevant part there:
https://github.com/collective/icalendar/blob/master/src/icalendar/cal.py#L186

It seems that the categories list is not recognized as such (matches the remove of ",".join(categories) in the commit, because it put a comma after each character – sign that a string was handed over.

Possible solutions:

  • put the comma separated list in a vText object
  • fix the issue that the categories field is not recognized as list. Fixing the join issue could be a milestone here.

@penguineer
Copy link
Contributor

I've just had a look into the proposed implementation and I vote for removing the lv:easy tag from #10. While it may seem easy to implement categories similar to location, there is the major difference that each TOOD has only one location with no further format, while there can be multiple categories.

We can take the easy route and store the categories comma-separated in a database text field. This would mostly mean:

  • put categories together when the parameter is repeated
  • initialize the Todo.categorie with None instead of []
    However, with this implementation it is hard to filter by a specific category, which is the ultimate goal.

Proper database design would suggest that there is a table with tuples (category, UID), where proper clean-up, aka remove all UID entries from this mapping when a UID is removed from the cache, is necessary.

Unless we go with the less complex, but also less efficient approach:

  • Use a text field to store a comma-separated list of categories
  • Filter categories by loading all Todos with a category and then check for each item if it matches the filter.
    I guess the only necessary fix for this solution is to convert the category string to vText before adding the field to the icalendar.Component.

@christf
Copy link
Author

christf commented Sep 19, 2018

ok, let's just lay out the tasks then.

@christf christf force-pushed the category branch 2 times, most recently from 0ff3d90 to 95ff7e6 Compare September 19, 2018 23:02
@christf christf changed the title Add support for categories. To fix #10 WIP: Add support for categories. To fix #10 Sep 19, 2018
@christf
Copy link
Author

christf commented Sep 19, 2018

unfortunately the model ties the name of the command line options and the name of the field in the ics file. So the option will be called --categories.

Copy link
Member

@WhyNotHugo WhyNotHugo left a comment

Choose a reason for hiding this comment

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

This is looking pretty good so far, thanks for the big effort (this is actually a lot less simple than I'd anticipated!).

I've mostly minor comments, and nothing critical. Thanks!

todoman/cli.py Outdated Show resolved Hide resolved
todoman/cli.py Outdated Show resolved Hide resolved
if categories is None or categories == '':
return None
else:
return categories
Copy link
Member

Choose a reason for hiding this comment

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

This should actually be return c for c in caterories.split(','), so that this returns a list of categories.

todoman/cli.py Outdated
@@ -355,6 +370,9 @@ def new(ctx, summary, list, todo_properties, read_description, interactive):

for key, value in todo_properties.items():
if value:
logger.debug("property: " + key + " value: " + ','.join(value) + " (" + str(type(value)) + ")" )
if key == "categories":
value = [v for v in value]
Copy link
Member

Choose a reason for hiding this comment

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

I believe this should actually be done in parse_category (see my other comment below).

todoman/cli.py Show resolved Hide resolved
@@ -159,6 +164,7 @@ def _save_inner(self):
self.todo.summary = self.summary
self.todo.description = self.description
self.todo.location = self.location
self.todo.categories = self.categories.split(',')
Copy link
Member

Choose a reason for hiding this comment

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

I believe we might also want to strip any whitespace in each category, so that Offline, Work ends up as Office and Work, rather than Office and Work. (note the extra space in the last one).

Maybe:

self.todo.categories = [c.strip() for c in self.categories.split(',')]

todoman/model.py Outdated Show resolved Hide resolved
self.vtodo.add(name, value)
if name == 'categories':
v = icalendar.prop.vInline(','.join(value))
self.vtodo.add(name, v)
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 using set_inline here actually sets the category property escaping commas as expected.

That means you also don't have to split when reading back from the cache.

todoman/model.py Show resolved Hide resolved
@WhyNotHugo
Copy link
Member

Regarding this comment:

unfortunately the model ties the name of the command line options and the name of the field in the ics file. So the option will be called --categories.

I believe it's possible to make the parameter name and flag name different, see here.

I know this documentation change is relatively recent, but I believe click>=6 has the same behaviour (as seen in 9b111c5)

Copy link
Member

@WhyNotHugo WhyNotHugo left a comment

Choose a reason for hiding this comment

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

Mostly looking pretty good. Let me know if you need any help with anything of have any doubts and I can take a closer look.

Thanks!

self.vtodo.add(name, value)
if name == 'categories':
# v = icalendar.prop.vInline(','.join(value))
v = self.vtodo.set_inline(name, value)
Copy link
Member

Choose a reason for hiding this comment

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

Looks like this needs to be if value is not None.

Copy link
Contributor

Choose a reason for hiding this comment

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

set_inline in the icalender library is defined here:
https://github.com/collective/icalendar/blob/master/src/icalendar/cal.py#L256

@WhyNotHugo
Copy link
Member

icalendar had some API changes around the whole categories part, so this PR might need some updating.
I've also had to update master to deal with those upstream changes, so there'll be new conflicts.

@penguineer
Copy link
Contributor

icalendar had some API changes around the whole categories part, so this PR might need some updating.

Shouldn't todoman specify the icalendar version in the requirements?

@WhyNotHugo
Copy link
Member

The latest version specifies a minimum version, due to this API change being backwards incompatible.

@penguineer penguineer mentioned this pull request Oct 19, 2018
Base automatically changed from master to main March 9, 2021 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants