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 correct overload for Write-Object in Get-Variable #8407
Conversation
Formally it is a breaking change. /cc @SteveL-MSFT @mklement0 Could you please look the change too? |
We don't cover the code by tests. 😕 |
The motivation for the change makes perfect sense to me and the change looks good. Nice catch, @vexx32. |
I can't really take the credit. @HumanEquivalentUnit stumbled across it trying to creatively troll someone on Reddit, apparently. 😂 I'll get some tests together during lunch. 😄 |
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.
Looks good if breaking change is approved and tests are added.
src/Microsoft.PowerShell.Commands.Utility/commands/utility/Var.cs
Outdated
Show resolved
Hide resolved
@iSazonov @PaulHigin For a minute I was thinking "typical And yet, despite a horrifically confusing error message, they do: /cc @nohwnd |
} | ||
} | ||
|
||
It 'Should return the same value with -ValueOnly as directly calling the variable returns' { |
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 test will be very confusing for someone if it fails. I think that this should do an explicit check to ensure a Get-Variable -ValueOnly collection is enumerated to the pipe, and not depend on Pester 'Should'. Maybe something similar to the original repro where the two cases are piped to Get-Member, then check type name.
Also, I think the 'It' description should be made more clear, or at least add a comment providing a clearer explanation of the test. Something about -ValueOnly should enumerate collections to output pipe.
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.
Get-Member is a bit of a chunky way to go, generating a lot of data we don't need... we ought to be able to do $v | % GetType
and gv v | % GetType
and compare instead with the same result.
I'll try to clarify the It
name. 😄
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.
Okay, I think that ought to be clear enough... let me know if I need to rethink it. 😄
Perhaps it could be reported to Pester. |
I have notified one of the maintainers both here and in the PowerShell Slack. I'll file an issue as well, just to be absolutely sure it's filed somewhere and not forgotten. 😄 |
Current test with checking types isn't good for me.
I think a key in the test is that |
@iSazonov This is the only especially sensible method I can think of apart from the Get-Member test. Interestingly, Which is perfectly correct, I suppose, but it doesn't seem to distinguish the enumerated/not enumerated like one can by checking the type directly; indeed, it seems to me that this may be the only straightforward method to do so. It's a bit of a tricky problem, and I acknowledge that there aren't a lot of good and easy ways to test it due to many cmdlets simply having an implicit assumption that piped objects will be enumerated and quietly handling those that don't, in an effort to make things like |
A pragmatic solution would be: (Get-Variable var1 -ValueOnly | Measure-Object).Count | Should -Be 3 If the array contained in |
@mklement0 Thanks! It would nice test. |
I also think that the approach that @mklement0 proposed is the easiest and most reliable. The reason for the assertion failure is the same. Internally Depending on your version of Pester you might consider adding a |
test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Variable.Tests.ps1
Outdated
Show resolved
Hide resolved
test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Variable.Tests.ps1
Outdated
Show resolved
Hide resolved
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
This PR has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs within 10 days. |
Pending committee decision. |
@PowerShell/powershell-committee reviewed this. Agree that there is inconsistency, but there isn't clear value to taking this breaking change (likely breaking Pester usage which is highly impactful and may represent wider usage of existing behavior). Need to verify we have sufficient documentation on existing behavior. |
@SteveL-MSFT can you expand upon how that would break Pester? |
@vexx32 looking at your example, we believed that Pester relies on current behavior. Correct us if that is not true. |
As far as I know (/cc @nohwnd as I'm sure he knows more than I where Pester's internals are concerned), Pester doesn't currently rely on Which example are you referring to? The example in the PR description doesn't have anything to do with Pester itself: $a = 1, 2, 3, 4, 5
$a | Get-Member
Get-Variable -Name a -ValueOnly | Get-Member These simply differ because with Get-Variable (and as far as I know, apart from The initial Pester test that I used to verify the behaviour is this: Get-Variable -Name var1 -ValueOnly | Should -Be $var1 And the reason this currently fails is simply because The only way this breaks Pester itself would be if someone was using that exact test format and relying on the behaviour of If it did rely on that behaviour, I think I would expect the test to continue to fail once the change is made in the Get-Variable cmdlet, and we definitely saw the behaviour change as expected judging by the CI results and my own local tests. I will of course respect the committee's decision, but I just want to make sure we're not retaining inconsistent behaviour without giving it a thorough look-see. 😄 |
@vexx32 thanks for the details. I think the overall conclusion from @PowerShell/powershell-committee is that we don't know how much impact there is with users relying on the current behavior. A simple search on GItHub turned up a number of scripts using |
Roger that, I appreciate you taking the time to clarify! Personally, I think consistency is super valuable but I also recognise that it's... dicey... at best to change long-standing behaviour for its sole sake. 😄 |
@vexx32 you analysis is correct. (If Pester relied on that behavior we could work around it by adding a case that would change based on the version of PowerShell, there are few conditional fixes and features like this already, but I also respect the decision of the committee of course :) ) |
@SteveL-MSFT Mostly for completeness' sake: I'm not an expert with GH search, but from what I can see, it appears that https://github.com/search?q=language%3APowerShell+%22Get-Variable+-ValueOnly+%7C%22&type=Code Scrolling through these results, I see a few common patterns:
It seems that in a majority of cases I can find, people are using it to code defensively (safely getting values in strict mode, for example) and as such are well aware of the limitation; I note around one instance of That said, however, I don't think this is enough to go on. There are a fair few alias-forms of the command and parameter that can be used, and in general I would expect less carefully-coded forms of the command to crop up more frequently in a search for those. For now I think we can probably leave it as-is -- but we absolutely should document this oddity. 😄 |
Such fixes is good candidates for next LTS version if we'll produce LTS versions. We could mark such PRs with "Next-LTS" label. |
Perhaps add this to #6745 |
PR Summary
Currently Get-Variable sends output to the pipeline without enumerating it when using
-ValueOnly
. This is at odds with almost every other cmdlet, and furthermore is at odds with the intuitive behaviour — I think it is reasonable to expect (indeed, that the intent for this switch is for) the variable value to be returned in the same manner as it is when simply calling the variable.In other words, it appears reasonable to expect that the two statements following the declaration should be equivalent:
If this behaviour is instead actually intentional, then it needs to be documented properly (it isn't), but I suspect it is more a matter of oversight than design here.
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
to the beginning of the title and remove the prefix when the PR is ready.[feature]
if the change is significant or affects feature tests