Skip to content

Conversation

@minchinweb
Copy link
Contributor

When renaming a project or a tag, update the "last_updated" time for the affected frames.

The other command in a similiar situation was edit, but it appears to already do this.

@willdurand willdurand requested a review from k4nar December 18, 2017 14:32
watson/cli.py Outdated
if old_name in frame.tags:
watson.frames[frame.id] = frame._replace(
tags=[new_name if t == old_name else t for t in frame.tags]
tags=[new_name if t == old_name else t for t in frame.tags],
Copy link
Contributor

Choose a reason for hiding this comment

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

There's a flake8 line-length error here:

Maybe we could make this a bit clearer:

                new_tags = [new_name if tag == old_name else tag
                            for tag in frame.tags]
                watson.frames[frame.id] = frame._replace(
                    tags=new_tags,
                    updated_at=updated_at
                )

BTW, please make sure that you have no tox failures, including in the flake8 tests, before submitting a PR.

@SpotlightKid
Copy link
Contributor

Thanks for the PR, good catch!

I'm weary of adding more code again to cli.py for which we still don't have tests yet. I think we should put everything from line 1175 on into new methods of the Watson class (e.g. rename_project and rename_tag) and add tests.

On Windows, timestamps must (typically) be greater than 3600, otherwise they throw an `OSError`
See dateutil/dateutil#197
(*arrow* depends on *dateutil*)
@minchinweb minchinweb force-pushed the update-time-on-rename branch from 1132130 to a7f1033 Compare December 18, 2017 17:01
@minchinweb
Copy link
Contributor Author

The test suite previously was spewing all sorts of errors for me, so I've fixed all the tests too (see d790bf7, the issue was dateutil + Windows + timestamps less than 3600). There remains one test that doesn't pass --> test_push, where it doesn't push any frames to the server....

I"ve refactored renaming projects and tags into the watson.py file, and added tests.

Copy link
Contributor

@SpotlightKid SpotlightKid left a comment

Choose a reason for hiding this comment

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

Tests pass. Good.

Test for Watson.rename_tag is missing.

the issue was dateutil + Windows + timestamps less than 3600

Can you show the errors you were getting?

If we change the time constants in the tests, we should at least add a comment explaining the reason. Better yet, we shouldn't use "magic numbers", but define them as constants at the top of the file. E.g.:

T_OFFSET = 4000

...

def test_frames_without_tags(mock, watson):
    content = json.dumps([[T_OFFSET, T_OFFSET + 10, 'foo', None]])

    mock.patch('%s.open' % builtins, mock.mock_open(read_data=content))
    assert len(watson.frames) == 1
    assert watson.frames[0].project == 'foo'
    assert watson.frames[0].start == arrow.get(T_OFFSET)
    assert watson.frames[0].stop == arrow.get(T_OFFSET + 10)
    assert watson.frames[0].tags == []

Maybe there's a way to make this change with some clever regex search & replace actions?

watson/watson.py Outdated
return report

def rename_project(self, old_project, new_project):
"""Takes a project and renames it in all affected frames."""
Copy link
Contributor

Choose a reason for hiding this comment

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

Docstring summary lines in imperative form, please.

"""Rename a project in all affected frames."""

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

watson/watson.py Outdated
style('project', new_project)))

def rename_tag(self, old_tag, new_tag):
"""Takes a tag and renames it in all affected frames."""
Copy link
Contributor

Choose a reason for hiding this comment

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

"""Rename a tag in all affected frames."""

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

watson/watson.py Outdated
def rename_project(self, old_project, new_project):
"""Takes a project and renames it in all affected frames."""
if old_project not in self.projects:
raise click.ClickException(style(
Copy link
Contributor

Choose a reason for hiding this comment

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

watson.pyshouldn't really depend on click, only cli.py should. I know, it was used already in Watson.__init__, but that has been bugging me for a long time and we shouldn't add new code using it in this file. Definitely not using exceptions or functions interacting with the console from it.

In this particular case, raise a ValueError here and catch that in cli.rename.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

watson/watson.py Outdated

self.frames.changed = True
self.save()
click.echo('Renamed project "{}" to "{}"'
Copy link
Contributor

Choose a reason for hiding this comment

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

User feedback should be in cli.py.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

watson/watson.py Outdated
def rename_tag(self, old_tag, new_tag):
"""Takes a tag and renames it in all affected frames."""
if old_tag not in self.tags:
raise click.ClickException(style(
Copy link
Contributor

Choose a reason for hiding this comment

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

Same applies as in rename_project.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

watson/watson.py Outdated

self.frames.changed = True
self.save()
click.echo('Renamed tag "{}" to "{}"'
Copy link
Contributor

Choose a reason for hiding this comment

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

User feedback should be in cli.py.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

moved

watson/watson.py Outdated
self.frames.changed = True
self.save()
click.echo('Renamed project "{}" to "{}"'
.format(style('project', old_project),
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd personally break the (previous) line after .format(.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

adjusted!

# renaming project updates frame last_updated time
def test_rename_project_with_time(mock, watson):
"""
Renaming a project should update any the "last_updated" time on any
Copy link
Contributor

Choose a reason for hiding this comment

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

update any the "last_updated"

--->

update the "last_updated"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

plus other code improvements as recommended by SpotlightKid
@minchinweb
Copy link
Contributor Author

minchinweb commented Dec 18, 2017

This is typical of the errors I was getting:

image


Moving to a T_OFFSET breaks in this case, because there is a static file frames-with-conflict that needs "offset" time values as well. watson.merge_report() would have to be refactored, as it currently expects a file.

Otherwise, the changes as suggested have been made, and a test for renaming tags has been added.

@SpotlightKid
Copy link
Contributor

This is typical of the errors I was getting:

Are you in a UTC-8 timezone ?

This actually uncovers a problem with Watson._parse_date, which expects a unix time stamp in UTC and tries to convert it into the local timezone, which, as your example shows, fail on some systems if the UTC offset is negative. To be honest, I'm a bit astonished and shocked to realize that Watson deals with local timestamps internally, instead of UTC ones. Anyway, we'll sort this out in another issue.

@minchinweb
Copy link
Contributor Author

I'm in UTC-7 (aka Mountain Standard Time).

Copy link
Contributor

@SpotlightKid SpotlightKid left a comment

Choose a reason for hiding this comment

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

A few further minor changes, if you don't mind...

watson/watson.py Outdated
def rename_project(self, old_project, new_project):
"""Rename a project in all affected frames."""
if old_project not in self.projects:
raise ValueError
Copy link
Contributor

Choose a reason for hiding this comment

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

raise ValueError("Project '%s' does not exist." % old_project)

watson/watson.py Outdated
def rename_tag(self, old_tag, new_tag):
"""Rename a tag in all affected frames."""
if old_tag not in self.tags:
raise ValueError
Copy link
Contributor

Choose a reason for hiding this comment

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

raise ValueError("Tag '%s' does not exist." % old_tag)

watson/cli.py Outdated
raise click.ClickException(style(
'error',
'Tag "%s" does not exist' % old_name
))
Copy link
Contributor

Choose a reason for hiding this comment

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

except ValueError as exc:
    raise click.ClickException(style('error'), str(exc))

watson/cli.py Outdated
raise click.ClickException(style(
'error',
'Project "%s" does not exist' % old_name
))
Copy link
Contributor

Choose a reason for hiding this comment

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

except ValueError as exc:
    raise click.ClickException(style('error'), str(exc))

@minchinweb
Copy link
Contributor Author

Changes made as recommended, but teach me why this second form is preferred...

@SpotlightKid
Copy link
Contributor

It's about different levels of abstraction.

If I use Watson.rename_project and it raises an exception because I passed a wrong project name, I want to get a proper error message. In cli.rename this error message is just passed on (we could use a differnt error message here, if the error message of the original exception is not user-friendly, but in this case it's fine).

Or do you mean the formatting of the error message?

@minchinweb
Copy link
Contributor Author

No, you answered my questions, and it makes sense. This way, if watson.rename_project() is called from elsewhere, a useful error message is available.

@SpotlightKid SpotlightKid merged commit 513f3c3 into jazzband:master Dec 21, 2017
@minchinweb minchinweb deleted the update-time-on-rename branch December 21, 2017 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants