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

Relax code style checks in python testing driver's testScripts's #72964

Closed
worldofpeace opened this issue Nov 7, 2019 · 34 comments · Fixed by #122201
Closed

Relax code style checks in python testing driver's testScripts's #72964

worldofpeace opened this issue Nov 7, 2019 · 34 comments · Fixed by #122201
Labels
0.kind: bug 6.topic: nixos 6.topic: testing Tooling for automated testing of packages and modules

Comments

@worldofpeace
Copy link
Contributor

Describe the bug
Currently the python testing driver runs this check on each test script

black --check --diff ${testDriverScript}

And this is great because it ensures a good code style within the testing scripts.
But unfortunately it isn't as straightforward as this, I can think of couple cases already where this can cause headaches for people

  • generated testing scripts/injected

I wrote

recently and it can error out on the final testing script, but that is already abstracted by this function so it doesn't really matter. I had to make special measure to try to appease black.

  • nix store paths/nix values

We used nix to keep line width manageable in this test

but if I were to port this to python I'd need to format the code like

machine.wait_until_succeeds(
    "su - alice -c '${startingUp} | grep -q true,..false'"
)

because those values get interpolated and then became really long.
Same if you use a nix store path attribute anywhere, it'll likely error out on the line being too long.

Solutions
We need to relax a lot of black's settings.
@adisbladis pasted these, as to what they're using personally:

And for sure relax string literal lengths to be larger, because of the reasons I mentioned.

@worldofpeace
Copy link
Contributor Author

worldofpeace commented Nov 7, 2019

Also, what if my test script isn't ready to be committed and I just want to run the vm.
You can't, you have to go and make sure your comments are lined up correctly.
Perhaps there should be a way to disable this, or maybe we should rethink this entirely.

@veprbl veprbl added the 6.topic: testing Tooling for automated testing of packages and modules label Nov 7, 2019
@FRidh
Copy link
Member

FRidh commented Nov 16, 2019

Somewhat related PR #73241.

Black is a formatter, not a linter. It will format it according to a certain spec. Contrary to yapf, it has no options besides line length. If you give it a length of say 1000 for the test scripts, then they will get messy if they include function definitions with many parameters and long parameter names.

Maybe we should avoid string interpolation, and instead write all configuration to a JSON file and let the test script load the relevant variables from a dictionary. In the future that JSON file could be .attrs.json once we use structured attributes. Downside of this approach is that, right now, you could generate your test script and see the exact values at the place of interest. Of course, by using variables you won't have that.

And indeed, maybe we should not use Black for the test scripts at all, and only for library code (the driver).

@adisbladis
Copy link
Member

And indeed, maybe we should not use Black for the test scripts at all, and only for library code (the driver).

I'm in strong favour of this approach. Sacrificing string interpolation is the wrong trade-off imho.
We could use a simple linter on the tests themselves and a formatter on the driver.

@khumba
Copy link
Contributor

khumba commented May 23, 2020

I think it's important to provide a way to fully disable style checks and style warnings for test scripts, at least for use outside of Nixpkgs. We use NixOS tests at work and it's not important for those scripts to conform to the style rules of NixOS's tests. The warnings during evaluation are just noise.

Could we possibly support skipLint = "silent" or something please? (Edit: If checking of the test scripts is kept at all, of course!)

@aszlig
Copy link
Member

aszlig commented Aug 27, 2020

Here are a few more examples of tests that are going to fail randomly when ported to Python:

The reason for this is that they're parametrized (eg. via the FQDN or subtest description) and black doesn't know about Nix string antiquotations.

Furthermore, I think using black on inline code also makes the code less readable, because it tends to fill more vertical space (eg. see the Chromium test before and after the conversion).

edit: One workaround would be to start every testScript with # fmt: off by default, so if we just document this accordingly that would be ugly but still work.

@flokli
Copy link
Contributor

flokli commented Aug 27, 2020

For testScript, could we use a code linter variant that behaves similar to black, except it ignores line lengths?

@flokli
Copy link
Contributor

flokli commented Aug 28, 2020

Moved over from #96396 (comment):

@Ma27:

I don't really see how this is related to removing a piece of code unused in nixpkgs, and announced to be removed half a year ago.

Well, there are people who also use one of the test frameworks for their own stuff and dislike this "feature" ;-)

You mean, it would be desirable to disable the linter without showing a warning for tests outside nixpkgs, that use the testing framework as a "library"? Or is it only the line lengths parts of the linter that are annoying?

I think having some sort of linting (probably not as strict as now) at least for everything in nixpkgs is desirable.

@Ma27
Copy link
Member

Ma27 commented Aug 28, 2020

You mean, it would be desirable to disable the linter without showing a warning for tests outside nixpkgs

Well, the thing is, it's not a warning, it's an error.

Please note though that I have a skipLint = true; in my VM-test snippet in $EDITOR and I fix errors before committing (if needed), I mainly tried to explain why this is kinda related to the removal of the perl driver).

Or is it only the line lengths parts of the linter that are annoying?

The second thing is the quote-linting. When I do some double- vs single-quote hackery I'm not that happy if the linter asks me to switch quotes because it's "simpler" (it isn't because a contributor has to fixup a small nitpick).

@flokli
Copy link
Contributor

flokli commented Aug 28, 2020

You mean, it would be desirable to disable the linter without showing a warning for tests outside nixpkgs

Well, the thing is, it's not a warning, it's an error.

Huh? If you instantiate the test with skipLint = true, you get a warning that linting is disabled, but the test runs.

Please note though that I have a skipLint = true; in my VM-test snippet in $EDITOR and I fix errors before committing (if needed), I mainly tried to explain why this is kinda related to the removal of the perl driver).

Or is it only the line lengths parts of the linter that are annoying?

The second thing is the quote-linting. When I do some double- vs single-quote hackery I'm not that happy if the linter asks me to switch quotes because it's "simpler" (it isn't because a contributor has to fixup a small nitpick).

Okay, so if we use a linter that doesn't complain about line lengths and doesn't suggest switching to "simpler" quotes, that'd be okay?

@Ma27
Copy link
Member

Ma27 commented Aug 29, 2020

Huh? If you instantiate the test with skipLint = true, you get a warning that linting is disabled, but the test runs.

Right, I guess I misunderstood your previous comment. I brought this up because folks who raised concerns in the perl-removal ticket didn't seem to be aware of this.

Okay, so if we use a linter that doesn't complain about line lengths and doesn't suggest switching to "simpler" quotes, that'd be okay?

Yes IMHO.

@flokli
Copy link
Contributor

flokli commented Sep 5, 2020

It seems #96515 from @khumba was closed due to black supporting # fmt: off.

@Ma27 I assume best plan forward would be proposing a PR switching from black to another linter, configured as described above.

@khumba
Copy link
Contributor

khumba commented Sep 5, 2020 via email

@flokli
Copy link
Contributor

flokli commented Sep 6, 2020

@khumba black itself isn't configurable, except turning it off entirely for a certain indentation level, and everything nested deeper (which might explain the errors you're seeing) - which is why I proposed switching to something else, that can be configured in #72964 (comment).

@stale
Copy link

stale bot commented Mar 5, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Mar 5, 2021
@blaggacao
Copy link
Contributor

blaggacao commented May 1, 2021

  • I researched and confirm black doesn't seem to allow disable only line lengths.
  • I confirm also that the warning with skipLint is triggering false alarm (on me*) and it is also extremly contxt free (Where is linting disabled? Does it hurt?)

* it is a big red warning when passing tests. I immediatly assume that something with the test subject is wrong as opposed to the test instrumentalization, since this is what I'm on the lookout when running tests. My brain immediatly goes in high alert in search for an error in the test subject. It's a context mismatch.


Since they appear to be harmful, is removing black checks (entirely) until we come up with a better solution an option?

Please note, this is a trade-off decision. Unfortunately, It currently can't be made pareto-efficient. But the current state is hurtful.

If no objection occurs within a few days, I'd feel compelled to assume consensus about a net gain associated with this decision and propose that change.

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label May 1, 2021
@jtojnar
Copy link
Member

jtojnar commented May 1, 2021

There was also a suggestion to patch the line length check out (or setting it to infinity or something).

@Ma27
Copy link
Member

Ma27 commented May 1, 2021

I confirm also that the warning with skipLint is triggering false alarm (on me)

Can you explain what that means exactly @blaggacao ? :)

@blaggacao
Copy link
Contributor

blaggacao commented May 1, 2021

@Ma27 Updated my post above, thanks for requesting clarification ❤️

@jtojnar

There was also a suggestion to patch the line length check out (or setting it to infinity or something).

I think the one individual preference that at first appears to be offset (by the categories of reasoning in pareto-efficiency terms) through removing black all together is a check for actual code validity.

However that would later be catched by the python interpreter in a much more explicit way I guess?

Traceback...

Vs

Oh No! :brokenheartemjoi: 1 file would be reformatted

Note in the second example it doesn't even mention it's black who's talking. Nor give any additional context. Really confusing / bad UX. I litterally had to search the internet (sic!) for the phrase segment ("file would be reformatted"), which happened to be sufficiently unique to have a hit within the black codebase. Then I searched the testing subtree of nixpkgs/nixos for black and only then did I understand the context. Before that, I was completely mislead / left stranded.

@Ma27
Copy link
Member

Ma27 commented May 1, 2021

  • it is a big red warning when passing tests. I immediatly assume that something with the test subject is wrong as opposed to the test instrumentalization, since this is what I'm on the lookout when running tests. My brain immediatly goes in high alert in search for an error in the test subject. It's a context mismatch.

Since I'm in fact the one responsible for this, let me explain why it looks the way it does:

  • I mainly wanted a flag to quickly turn off linting for writing tests (hence the short, probably suboptimal name) because linting for each new nix-build significantly slowed down my dev cycle. The warning exists to make sure that nobody forgets to remove this before committing to nixpkgs.
  • I used lib.warn to print a warning to remain consistent with any other thing in nixpkgs that decides to warn about anything during evaluation. The function is defined in lib/trivial.nix and basically does a builtins.trace and adds the ANSI color code for red in front of the message. So if we want to change the color, we should do it directly there, otherwise it would be inconsistent IMHO.
  • Regarding the name: one objective for me is (still) that it has to be rather short. But I agree that without sufficient context it can be kinda confusing. May I ask if you have a better suggestion? At the bottom of https://nixos.org/manual/nixos/stable/#sec-writing-nixos-tests is also a short explanation (but now that I re-read it, it entirely misses the fact that it disables python linting). Apart from that, is there anything else to improve?

@blaggacao
Copy link
Contributor

blaggacao commented May 1, 2021

May I ask if you have a better suggestion?
Apart from that, is there anything else to improve?

Hm, I didn't want to enter that discussion, because sure there always is.

To reasonably limit my deployment of available resources, my quest here really just is about to find out if we can have a "non-vetoed" consensus about a genuine "trade-off"-type decision (non-pareto efficient) about the removal of the black check for their current "harmfulness" (whatever that means, doesn't really matter as long as they cause some sort of "stumbling").

I find it completely fine to veto this, even without reason (of course, reason is always nice). If this is vetoed, I won't assume consensus and won't proceed to make the proposed change in a few days.

(A veto also makes my life easier, since I wouldn't have to follow through on my commitment 😉)

@flokli
Copy link
Contributor

flokli commented May 1, 2021

@blaggacao do keep this brief, let me quote my comment from above:

I assume best plan forward would be proposing a PR switching from black to another linter, configured as described above.

Feel free to open a PR for this.

@blaggacao
Copy link
Contributor

blaggacao commented May 1, 2021

Feel free to open a PR for this.

@flokli I'm unable to parse this as either a veto or an absence of veto to my orginal proposed course of action. Can you clarify?

I, unfortunatly, would have to opt for letting go on your proposed alternative course of action. I hope you understand.

@blaggacao
Copy link
Contributor

blaggacao commented May 2, 2021

I'll be desisting for lack of clarity and I don't have a sense clarity is obtained within reasonable effort here.

Don't get me wrong, positions are clear. But not at all what my options to help out with this are.

In such conditions, I don't want to pick this up anymore.

This issue is free to take, again.

@domenkozar
Copy link
Member

The minimal change that would get us 80% there is a boolean to switch black off.

@Ma27
Copy link
Member

Ma27 commented May 2, 2021

@domenkozar I'm not sure if I'm misunderstanding you, but this is what can be done by setting skipLint = true; in a VM test. As discussed in the PR where I added this, this should not be commited into nixpkgs (I started using it by default for my private VM tests though :P), but it helps at least pretty much for faster development.

@blaggacao I'm confused. First up, I asked for how to improve the semantics of an existing thing, so a purely cosmetic change, nothing too controversial about that, right? Also, let me put it like this, is there anything wrong with the suggestion to patch this away @jtojnar brought up?

@blaggacao
Copy link
Contributor

blaggacao commented May 2, 2021

I chose to clear up the confusion in a PM with the involved parties: I'll report back on the outcome, if any.

@Ma27
Copy link
Member

Ma27 commented May 2, 2021

Just wrote an answer. The problem was that I missed your initial suggestion about a full removal of black, also in public, sorry for that! For the record, I'm absolutely not opposed to that, hence definitely no veto from my side.

@flokli
Copy link
Contributor

flokli commented May 3, 2021

I think we want some kind of linter, to spot very obvious mistakes, and ensure some consistency in the way tests inside nixpkgs are structured. There's similar efforts to have this for other non-compiled scripts, like piping shellscripts through shellcheck.

So far, the linter is mostly fine for nixpkgs, it can be disabled for out-of-nixpkgs usage where people don't care, or in-nixpkgs during development.

It could be made more ergonomic, by disabling the line length checks in our existing linter, but so far since September 2020 noone bothered enough to tackle this.

I'd personally have huge reservations against simply removing the linter. We should either come up with a more relaxed linter (as the issue title requests), or better docs, so people can use skipLint during development, and only need to fight the slightly-overzealous linter in a single pass at the end.

@blaggacao
Copy link
Contributor

blaggacao commented May 4, 2021

I think we want some kind of linter, to spot very obvious mistakes, and ensure some consistency in the way tests inside nixpkgs are structured.

The current state of technological advancement offers formatters, often times integrated into pre-commit hooks or directly within the IDE on save.

As a general guideline, out of respect for our users, we should probably care not to fall too far behind that "current state of technology".

@roberth
Copy link
Member

roberth commented May 4, 2021

Please don't conflate formatters and linters. I don't think anyone has a problem with a python linter. It's the formatter that does more harm than good in this case.

state of advancement offers formatters [...] pre-commit [...] on save

Typically these are only capable of formatting a single language. They don't know the language used in string literals and such, and they can't easily call other formatters because the content of the literal may not be valid without running the program.
While it's not impossible to accomplish, it's just not that simple.
If someone wants to integrate formatters in such a way, that would be great, but let's not a hold our breath. After all, we use Nix to solve real problems, not for code to look nice and not to avoid trivial merge conflicts at any cost.

The minimal change that would get us 80% there is a boolean to switch black off.

@blaggacao
Copy link
Contributor

blaggacao commented May 4, 2021

Please don't conflate formatters and linters. I don't think anyone has a problem with a python linter. It's the formatter that does more harm than good in this case.

Oh, I think you probably misread my general opinion as a conflation. That was not the intended message, I'm sorry.

The intended message was: if we do linting, then we probably should care to do it in a comparable UX way as people are accustomed to. That does not mean we must do it, but we should at least care for that aspect.

I think the current situation does not reflect very much of a care for modern UX considerations.

@roberth
Copy link
Member

roberth commented May 8, 2021

This is such a waste of energy.

#80068 (comment)

@roberth
Copy link
Member

roberth commented May 8, 2021

#122197

aszlig added a commit to aszlig/nixpkgs that referenced this issue May 8, 2021
So far, we have used "black" for formatting the test code, which is
rather strict and opinionated and when used inline in Nix expressions it
creates all sorts of trouble.

One of the main annoyances is that when using strings coming from Nix
expressions (eg. store paths or option definitions from NixOS modules),
completely unrelated changes could cause tests to fail, since eg. black
wants lines to be broken.

Another downside of enforcing a certain kind of formatting is that it
makes the Nix expression code inconsistent because we're mixing two
spaces of indentation (common in nixpkgs) with four spaces of
indentation as defined in PEP-8. While this is perfectly fine for
standalone Python files, it really looks ugly and inconsistent IMO when
used within Nix strings.

What we actually want though is a linter that catches problems early on
before actually running the test, because this is *actually* helping in
development because running the actual VM test takes much longer.

This is the reason why I switched from black to pyflakes, because the
latter actually has useful checks, eg. usage of undefined variables,
invalid format arguments, duplicate arguments, shadowed loop vars and
more.

Signed-off-by: aszlig <aszlig@nix.build>
Closes: NixOS#72964
@aszlig aszlig linked a pull request May 8, 2021 that will close this issue
@roberth
Copy link
Member

roberth commented May 8, 2021

We're switching to an actual linter. Please help correct the findings here #122201 (comment)

Time for action!

@aszlig aszlig closed this as completed in c362a28 May 9, 2021
aszlig added a commit that referenced this issue May 9, 2021
This switches the linting of the NixOS test driver script from Black
(which is a code *formatter*) to PyFlakes. Contrary to Black, which only
does formatting and a basic syntax check, PyFlakes actually performs
useful checks early on before spinning up VMs and evaluating the actual
test script and thus becomes actually useful in development rather than
an annoyance.

One of the reasons why Black has been an annoyance[1] was because it
assumed that the files that it's formatting aren't inlined inside
another programming language.

With NixOS VM tests however, we inline these Python scripts in the
testScript attribute. With some of them using string antiquotations,
things are getting rather ugly because Black now no longer formats
static code but generated code from Nix being used as a macro language.

This becomes especially annoying when an antiquotation contains an
option definition from the NixOS module system, since an unrelated
change might change its length or contents (eg. suddenly containing a
double quote) for which Black will report an error.

While issue #72964 has been sitting around for a while (and probably
annoyed everyone involved), nobody has actually proposed an
implementation until @roberth did a first pull request[2] yesterday
which added a "skipFormatter" attribute, which contrary to skipLint
silently disabled Black.

This has led to very legitimate opposition[3] from @flokli:

> As of now, this only adds an option that does exactly the same as the
> already existing one.
>
> black does more than linting, yes. Last September it was proposed to
> switch from black to to a more permissive (only-)linter.
>
> I don't think adding another option (skipFormatter) that currently
> does exactly the same as skipLint will help out of this confusion.
>
> IMHO, we should keep skipLint, but use a linter that doesn't format,
> at least not enforce the line length (due to the nix interpolation we
> do).

This was written while I was doing an alternative implementation and
pretty much sums up the work I'm merging here, which switches to
PyFlakes, which only checks for various errors in the code (eg.
undefined variables, shadowing, wrong comparisons and more) but does not
do *any* formatting.

Since Black didn't do any of the checks performed by PyFlakes (except a
basic syntax check), the existing test scripts needed to be fixed.

Thanks to @blaggacao, @Ma27 and @roberth for helping with testing and
fixing those scripts.

[1]: #72964
[2]: #122197
[3]: #122197 (review)
roberth added a commit to roberth/nixpkgs that referenced this issue May 9, 2021
Annoyed with the interference of the python formatting of
generated code (see NixOS#72964), I took matters into my own hands
as maintainer of dockerTools.

Afterwards, I've created a PR, hoping to unstuck the discussion.

@aszlig took notice and thanks to his python ecosystem knowledge,
the testing efforts of @blaggacao and @Ma27, and a sense of
shared suffering and comraderie we were able to change the
situation for the better in NixOS#122201.

Now, we have a proper linter that actually helps contributors,
so it's time to turn it back on again.

I'm glad we could make it happen this quickly!

Thanks!

This reverts commit 4035049.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
0.kind: bug 6.topic: nixos 6.topic: testing Tooling for automated testing of packages and modules
Projects
None yet
Development

Successfully merging a pull request may close this issue.