-
Notifications
You must be signed in to change notification settings - Fork 77
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
Use tomorrow and today while formatting date #108
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In principle this looks good to me, still have a few nitpicks.
Also you have a few styleguide violations. After running pip install tox
, you can get all style nitpicks using tox -eflake8
.
EDIT: The output is also available here: https://travis-ci.org/pimutils/todoman/jobs/203232655#L249
todoman/ui.py
Outdated
if date: | ||
rv = date.strftime(self.date_format) | ||
date_tomorrow = datetime.today().date() + timedelta(days = 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of calling datetime.today()
here, please use self.now
. This is because we might want to replace self.now
with a fixed value in the testsuite.
todoman/ui.py
Outdated
date_tomorrow = datetime.today().date() + timedelta(days = 1) | ||
# Get a dictionary which stores the dates for which we don't have to merely | ||
# return a date string and map it to the special string we need to return | ||
dates_for_which_not_to_return_simple_date = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite a long variable name, I suggest something like special_dates
.
todoman/ui.py
Outdated
datetime.today().date() : "Today", | ||
date_tomorrow : "Tomorrow" , | ||
} | ||
if date in dates_for_which_not_to_return_simple_date.keys(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.keys()
is not necessary, just if date in dates_for_which_not_to_return_simple_date
.
Thanks @untitaker for your kind help! Looking forward to correct my mistakes |
Hello @untitaker, do I need to write a test case for testing this feature? |
todoman/ui.py
Outdated
self.now.date(): "Today", | ||
date_tomorrow: "Tomorrow", | ||
} | ||
if date in special_dates(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to write special_dates
instead of special_dates()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! Sorry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to apologize!
That would be nice. You have two options:
|
Hi. Thanks for picking this up with be being a bit away, @untitaker. Another detail is that, if you run You can probably do something like |
The line which is making flake8 violations is here: return special_dates[date] if date in special_dates else date.strftime(self.date_format) Isn't it the optimal way of doing it or should I switch back to the if-else tree? |
@rimshaakhan The line is too long. I personally prefer the if-else variant. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks quite on the right track, but there's some tiny optimizations I'd like to see.
We're a bit picky with code being very well polished, so don't feel unmotivated by all the back and forth. 😄
Again, feel free to ask any questions you may have.
todoman/ui.py
Outdated
# Get a dictionary which stores the dates for which | ||
# we don't have to merely return a date string and | ||
# map it to the special string we need to return | ||
WIDTH = len(date.strftime(self.date_format)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, len(empty_date)
was fine. They should both have the same with, and we avoid formatting this date when it's [possibly] unnecessary.
I'd also prefer move this over to __init__
, so we only calculate this width once, instead every time we format a date (pretty much like we only calculate empty_date
once.
Let me know if you're not very familiar with contructors/__init__
or if this is otherwise unclear.
Also, date_width
is actually a better variable name, but that one's my fault because I used WIDTH
on my example, which really was a bad idea on my part, sorry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you would want something like this:
def __init__(self, date_format):
self.date_format = date_format
self._localtimezone = tzlocal()
self.now = datetime.now().replace(tzinfo=self._localtimezone)
# An empty date which should be used in case no date is present
self.empty_date = " " * len(self.format_date(self.now))
self.date_width = len(self.empty_date)
self.date_tomorrow = self.now.date() + timedelta(days=1)
# Get a dictionary which stores the dates for which
# we don't have to merely return a date string and
# map it to the special string we need to return
self.special_dates = {
self.now.date(): "Today".rjust(self.date_width, " "),
self.date_tomorrow: "Tomorrow".rjust(self.date_width, " "),
}
self._parsedatetime_calendar = parsedatetime.Calendar()
But then wouldn't self.empty_date
call self.format_date
, where self.date_width
and self.special_dates
still won't exist and there would be an exception.
Should we find a different way for calculating self.empty_date
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh, you're completely right, I missed that! I think we need to rewrite how we calculate empty_date
and avoid that trap:
empty_date = self.now.format(self.date_format)
I don't think we need the comment explaining what that dictionary is; it seems quite clear. Maybe just a short one-liner, at most.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, since self.empty_date
calls self.format_date(self.now))
, it would not be an empty_date, rather something like " Today" (ideally - when we can get the code to run) and I think it would hinder the utility of having an empty_date and therefore would render it useless! :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops (again!). Not by best day. I meant this:
self.date_width = len(self.now.format(date_format))
self.empty_date = " " * self.date_width
todoman/ui.py
Outdated
# map it to the special string we need to return | ||
WIDTH = len(date.strftime(self.date_format)) | ||
special_dates = { | ||
self.now.date(): "Today".rjust(WIDTH, " "), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the same as above; define the strings in the constructor.
No, I am not feeling demotivated, but on the contrary it gets even more exciting and adventurous. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good, I think the only thing missing are:
- tests (see above, I suspect option 2 may be easier)
- changelog entry (probably)
- Adding yourself to AUTHORS
the requests in this review have been addressed
FWIW, these final items are listed in the patch review checklist. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM so far, just authorship and tests 🎉
todoman/ui.py
Outdated
@@ -204,8 +204,16 @@ def __init__(self, date_format): | |||
self.date_format = date_format | |||
self._localtimezone = tzlocal() | |||
self.now = datetime.now().replace(tzinfo=self._localtimezone) | |||
self.empty_date = " " * len(self.format_date(self.now)) | |||
|
|||
self.date_tomorrow = self.now.date() + timedelta(days=1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just call this self.tomorrow
, for consistency.
What should be added to changelog? Perhpas, just a line saying: |
I would rather describe the concrete changes to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In #109 @hobarrera noticed that this PR has a bug
todoman/ui.py
Outdated
@@ -251,8 +259,18 @@ def detailed(self, todo): | |||
return rv | |||
|
|||
def format_date(self, date): | |||
""" | |||
:param datetime.date date: a datetime object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact format_date
recieves a datetime object (i.e. datetime.datetime
instead of datetime.date
). It is probably useful to add an assert isinstance(date, datetime)
in format_date
.
todoman/ui.py
Outdated
if date: | ||
rv = date.strftime(self.date_format) | ||
if date in self.special_dates: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since date
is a datetime (I know, misleading variable name), you need to use date.date()
here, otherwise special_dates
is never used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sorry, this is something we've dragged for a while. #109 will fix this in future, but for now, just update this to date.date()
.
tests/test_formatter.py
Outdated
Tests the format_date function in todoman.ui.TodoFormatter | ||
""" | ||
formatter = ui.TodoFormatter(DATE_FORMAT) | ||
today = datetime.now().date() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make today
a datetime
instead of date
@rimshaakhan if you run |
The color checking test: @pytest.mark.parametrize('hours', [72, -72])
def test_color_due_dates(tmpdir, runner, create, hours):
due = datetime.datetime.now() + datetime.timedelta(hours=hours)
create(
'test.ics',
'SUMMARY:aaa\n'
'STATUS:IN-PROGRESS\n'
'DUE;VALUE=DATE-TIME;TZID=ART:{}\n'
.format(due.strftime('%Y%m%dT%H%M%S'))
)
result = runner.invoke(cli, ['--color', 'always'])
assert not result.exception
due_str = due.strftime('%Y-%m-%d')
if hours == 1:
assert result.output == \
' 1 [ ] {} aaa @default\x1b[0m\n'.format(due_str)
else:
assert result.output == \
' 1 [ ] \x1b[31m{}\x1b[0m aaa @default\x1b[0m\n'.format(due_str) is failing with the error message:
Can someone please share any insight @hobarrera @untitaker ? |
Yes, in that test there is a line called |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's that tiny change and we're done. 🎉
CHANGELOG.rst
Outdated
@@ -23,6 +23,7 @@ v2.1.0 | |||
* Fix crash when running ``--porcelain show``. | |||
* Show ``id`` for todos everywhere (eg: including new, etc). | |||
* Add the ``ctrl-s`` shortcut for saving in the interactive editor. | |||
* Show "Today" or "Tomorrow" when due date is today or tomorrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v2.1.0 was released a couple of days ago, so you need to move this up. ^_^
Note that I try and keep things in reverse-chronological order too, so it should be at the very top.
todoman/ui.py
Outdated
@@ -251,8 +259,19 @@ def detailed(self, todo): | |||
return rv | |||
|
|||
def format_date(self, date): | |||
""" | |||
:param datetime.datetime date: a datetime object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:param:
need to be at the bottom of the docstring, not at the top.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which editor do you use @rimshaakhan? There are probably plugins which immediately tell you about styleguide violations using flake8.
tests/test_formatter.py
Outdated
formatter = ui.TodoFormatter(DATE_FORMAT) | ||
today = datetime.now() | ||
tomorrow = today + timedelta(days = 1) | ||
any_day = today + timedelta(days = randrange(2, 8)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So close! A styleguide violation here, no spaces around the =
. Same for the previous line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @untitaker, I am using Sublime Text 3
It was so close! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Back when I used sublime I used a plugin called Anaconda
that did some python style checks and stuff (don't recall what else). Might be worth looking into.
I think this review comment is still pending, but then that'd be really it :) |
Also, should I consider filing a issue because I am unable to filter out results when I run Please have a look at the log file |
Scrub that, that'll also fail. |
Yeah! that was the command I ran, but didn't quite well worked for me! |
No, it's not really anything you've done. Personally, I never came across that because I use |
Thanks for you contribution! 🎉 |
In general I would recommend creating the virtualenv outside of the git repository, otherwise you may accidentally commit it into git, or misconfigured tools may crawl it like pytest or flake8. |
@hobarrera You just beat me up while I was writing this Thank You :) I am looking forward to apply for RGSoC and am very excited to learn: how to make fascinating code which looks so amazingly beautiful! Its a wonderful feeling of seeing myself in the author list |
@rimshaakhan "beat me up" doesn't mean what you think it does! :D It has been a pleasure working with you so far! |
@untitaker Should I re-configure for the same! |
fixes #82