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

feat: add dry-run option #78

Merged
merged 4 commits into from
Oct 8, 2018
Merged

Conversation

max-wittig
Copy link
Contributor

No description provided.

@peterbe
Copy link
Owner

peterbe commented Oct 2, 2018

I restarted the failing (3.6) tests.

Copy link
Owner

@peterbe peterbe 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 great! I'm tempting to land it as is but there's one major thing that I don't like and that it doesn't actually test what changes would be made.

See:

dev/PYTHON/hashin  (63a92a9...) ✔                                                                            
▶ touch /tmp/reqs.txt
dev/PYTHON/hashin  (63a92a9...) ✔                                                                            
▶ python hashin.py -r /tmp/reqs.txt requests
dev/PYTHON/hashin  (63a92a9...) ✔                                                                            
▶ python hashin.py -r /tmp/reqs.txt --dry-run requests
requests==2.19.1 \
    --hash=sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1 \
    --hash=sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a

What it actually should notice is that the version of requests hasn't actually changed in /tmp/reqs.txt.

README.rst Outdated Show resolved Hide resolved
@peterbe
Copy link
Owner

peterbe commented Oct 3, 2018

So, your patch is this:

    if dry_run:
        if verbose:
            _verbose('Dry run, not editing ', file)
        print(new_lines)
        return
    if verbose:
        _verbose('Editing', file)
    with open(file) as f:
        requirements = f.read()
    requirements = amend_requirements_content(
        requirements,
        package,
        new_lines
    )
    with open(file, 'w') as f:
        f.write(requirements)

Perhaps what we could do is something like this:

    if verbose:
        _verbose('Editing', file)
    with open(file) as f:
        requirements = f.read()
    requirements = amend_requirements_content(
        requirements,
        package,
        new_lines
    )
    if dry_run:
        if verbose:
            _verbose('Dry run, not editing ', file)
        with open(file) as f:
            old_requirements = f.read()
        print(diff(old_requirements, requirements))
    else:
        with open(file, 'w') as f:
            f.write(requirements)

What do you think?

@max-wittig
Copy link
Contributor Author

max-wittig commented Oct 4, 2018

@peterbe Thanks for the review. Will fix it probably on the weekend

@max-wittig
Copy link
Contributor Author

@peterbe Actually I'm not sure about the diff. It would remove my use-case for this function.

Normally I use pipenv for handling lock files, hashes etc.
But to install pipenv in a CI environment, I need to use pip with hashes.
Using hashin directly is not possible, because hashin doesn't actually resolve all dependencies of a requirements, so when I run hashin pipenv I only get the hashes for pipenv itself.
But actually I also want the hashes for all dependencies of pipenv. To accomplish that I usually:

  1. Install everything with pip in a virtualenv
  2. Freeze all packages
  3. Run this cat requirements.txt | while read line; do hashin -v $line; done
  4. Rename the requirements to requirements-pipenv.txt
  5. Run pip install --require-hashes -r requirements-pipenv.txt
  6. Use pipenv for all other packages e.g. pipenv install requests

With the dry-run feature I could quickly copy&paste everything into the requirements-pipenv.txt file and be done with it.

Maybe dry-run is simply the wrong name for this and I need to open a separate PR after this one. What do you think?

@max-wittig
Copy link
Contributor Author

@peterbe Thinking more about it, I've applied your diff approach now.

Maybe I will open a separate PR with another argument later (e.g. --raw)

@mythmon
Copy link
Contributor

mythmon commented Oct 5, 2018

@max-wittig I don't totally follow what you're trying to do, but have you seen the -r option for hashin? It changes the file that hashin writes to. Would that help your current workflow?

@max-wittig
Copy link
Contributor Author

@peterbe I will look into it. I've made your requested changes for this PR. I think some people will still find it useful 😄

Copy link
Owner

@peterbe peterbe left a comment

Choose a reason for hiding this comment

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

Thanks for being understand and that you're not giving up on this PR even if it might not be what you're after.

README.rst Outdated

@@ -3,3 +3,6 @@

--hash=sha256:ad2edb7da2fc50a1d1a117cc9cfd8fc1f8b30c8b04932d5efef4fb09cbb2e984
Copy link
Owner

Choose a reason for hiding this comment

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

There's too many empty newlines in this diff output. Also, see my comment below about unified_diff.


# Check dry run output
out_lines = my_stdout.getvalue().splitlines()
print(out_lines)
Copy link
Owner

Choose a reason for hiding this comment

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

Debug leftover.

@@ -53,5 +56,6 @@ def test_minimal():
verbose=False,
version=False,
include_prereleases=False,
dry_run=False,
Copy link
Owner

Choose a reason for hiding this comment

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

Isn't this the default anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tests fail otherwise here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I leave it like this or what changes should be made?

tests/test_arg_parse.py Outdated Show resolved Hide resolved
hashin.py Outdated
@@ -175,17 +182,25 @@ def run_single_package(
new_lines += ' \\'
new_lines += '\n'

if verbose:
_verbose('Editing', file)
with open(file) as f:
requirements = f.read()
Copy link
Owner

Choose a reason for hiding this comment

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

Change this to old_requirements = f.read() and 2 lines down pass in old_requirements (instead of requirements) to the amend_requirements_content function.
Then you don't need lines 195-196 since you'll already have a copy of the whole old file content.

hashin.py Outdated
with open(file) as f:
old_requirements = f.read()
for line in difflib.unified_diff(old_requirements.splitlines(), requirements.splitlines()):
print(line)
Copy link
Owner

Choose a reason for hiding this comment

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

The correct way to print a nice diff is to do it like this:

old = """
One
Two
Three
""".strip()

new = """
One
One and a half
Twoish
Three
""".strip()


print(
    "".join(
        difflib.unified_diff(
            old.splitlines(True), new.splitlines(True), fromfile="Old", tofile="New"
        )
    )
)

Then you get an output which resembles what you get with git diff kinda:

--- Old
+++ New
@@ -1,3 +1,4 @@
 One
-Two
+One and a half
+Twoish
 Three

This snippet works in Python 2 and Python 3.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for all this help in fixing the MR!

Copy link
Owner

@peterbe peterbe left a comment

Choose a reason for hiding this comment

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

Did you want to take a look @mythmon ?

Copy link
Contributor

@mythmon mythmon left a comment

Choose a reason for hiding this comment

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

I have a couple nits, but overall this looks good to me.

README.rst Outdated

There are some use cases, when you maybe don't want to edit your ``requirements.txt``
right away. You can use the ``-dry-run`` argument to just print the lines, as if they
would be added to your requirements.txt file.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that this still should have backticks aroud requirements.txt. Also, the argument is listed as -dry-run with only one -, when it should two.

More holistically, didn't this change so that it shows a diff, isntead of "just print[ing] the lines"?

hashin.py Outdated
@@ -75,6 +76,12 @@
action='store_true',
default=False,
)
parser.add_argument(
'--dry-run',
help='Don\'t touch requirements.txt and just show hashes',
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Most style guides allows for switching quotes to avoid escaping quotes in a string.

Copy link
Owner

Choose a reason for hiding this comment

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

I wouldn't worry about this one. Once this PR is squared away there are no open PRs and I can take a massive knife of black and therapist to this code base and then these kinds of nits become unimportant.

@peterbe peterbe merged commit 32445d8 into peterbe:master Oct 8, 2018
@peterbe
Copy link
Owner

peterbe commented Oct 8, 2018

hashin 0.13.4 just released.

@max-wittig max-wittig deleted the feat/dry-run branch October 8, 2018 14:31
@max-wittig max-wittig mentioned this pull request Oct 18, 2018
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.

3 participants