Skip to content

(fix) Proposing a workaround for superfluous indentation on multi-lines #66

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

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

Conversation

MementoRC
Copy link
Contributor

May address issue:#12
Was proposed to resolve wrapping a multi-line ast.Call into an ast.Await without having changes in the indentation of the secondary lines

The solution proposed is assuming that often the Replace would only change the first line of an ast.Expr and lose the original indentation (thus later on having to add it), however, the replacement ends-up having the original indentation for the lines that are left unchanged. The proposal is to check that the lines are indeed not the same before applying the block indentation

This is not robust, but more like a workaround

@MementoRC
Copy link
Contributor Author

Adding more clunk: Addressing the case of multi-lines F-string with parenthesis: #74

Copy link
Owner

@isidentical isidentical left a comment

Choose a reason for hiding this comment

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

Thanks so much @MementoRC for the PR (and so sorry for the delay on the review!!). I have a few suggestions / minor comments, let me know if you'd like to handle them (or I can also try to push them myself to your branch if that works for you)

@MementoRC
Copy link
Contributor Author

Thank you very much for the review. This is a learning exercise for me! I would like to go through your review and update the PR, so that it becomes less work on your side. I first needed to know that the approach is acceptable
Also, I wanted to maintain the backward compatibility, in case I was missing something more intricate

refactor/ast.py Outdated
Comment on lines 50 to 53
def not_original(i: int) -> bool:
common_chars: str = commonprefix([str(self.data[i]), str(source_lines.data[i].data)])
is_multiline_string: int = str(self.data[i]).find(common_chars) == 0 and common_chars in ["'''", '"""']
return not (i < len(source_lines.data) and (str(self.data[i]) == common_chars or is_multiline_string))
Copy link
Owner

Choose a reason for hiding this comment

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

So if we reduce it to bare minimum (let's drop the multiline strings for now, just to make this patch simpler), what this does is basically checking if the original line starts with the replaced line and if it is the case we skip indenting?

A better way to express it might be this:

        for index, line in enumerate(self.data):
            if index < len(source_lines):
                original_line = source_lines[index]
            else:
                original_line = None

            if index == 0:
                self.data[index] = indentation + str(start_prefix) + str(line)  # type: ignore
            elif original_line is not None and original_line.startswith(line):
                self.data[index] = line # type: ignore
            else:
                self.data[index] = indentation + line  # type: ignore

But I am still unsure on how this should work in different scenarios, would love to see a few more examples (or actually tests) where the indentation is preserved for the first argument (when replacing the whole call), the middle arguments, the last argument (maybe introduce a new argument or remove one from the middle).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It only works when the Call is unchanged, removing or adding arguments does not maintain the original form, but collapses the Call into one line. The case I was working with was wrapping the Call in Await and it works well in that case

There is something I don't understand though, I added a few tests (bear with my padawan-level) and the Issue #12 pass, but in the complete_rules it does not, it'd be great if you took a look at those tests, I must be doing something (or more) incorrectly

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, the issue was that in the test_ast.py, I use the full source_lines (with indent=0 and thus is not added to the failing line), but in the test_complete_rules.py only the changed source line is passed (because of the view), so the indentation is there and the test fails.
Now, the 'multi-line' issue is more of a "within parens" issue, so would it be acceptable to just have this:
elif original_line is not None and (original_line.startswith(line) or line[-1] in (")}]")):
This way the test passes

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.

2 participants