Make -NoTypeInformation Default on Export-Csv and ConvertTo-Csv#5164
Make -NoTypeInformation Default on Export-Csv and ConvertTo-Csv#5164iSazonov merged 5 commits intoPowerShell:masterfrom
Conversation
| } | ||
| } | ||
| private bool _includeTypeInformation; | ||
| private bool _includeTypeInformationIsSet; |
There was a problem hiding this comment.
In ProcessRecord() we use only if (NoTypeInformation == false).
So I believe we should use auto-implemented property for IncludeTypeInformation and NoTypeInformation and check IncludeTypeInformation.IsPresent.
There was a problem hiding this comment.
I did testing with that.. and... it resulted in conflicts when using @splatting and supplying both. :( I ultimately went with this method because it was the most reliable way to detect if both were supplied.
edit: for clarity, when you supply $false to a switch parameter, IsPresent reports false. either by -Switch:$false or $hash = @{Switch = $false}; command @hash
There was a problem hiding this comment.
As for @splatting - maybe it is a bug in @splatting ?
I think we should remove NoTypeInformation everywhere in code and leave only its declaration - the parameter is dummy and we should ignore it in code at all.
There was a problem hiding this comment.
It's not a bug in splatting. Its the nature of how switch params work. IsPresent is does not mean was supplied but more user supplied $true
Function Test-SwitchParam {
param(
[Switch]$Switch
)
"Switch: {0}" -f $Switch
"Switch.IsPresent: {0}" -f $Switch.IsPresent
" "
}
'Test-SwitchParam'
Test-SwitchParam
'Test-SwitchParam -Switch'
Test-SwitchParam -Switch
'Test-SwitchParam -Switch:$true'
Test-SwitchParam -Switch:$true
'Test-SwitchParam -Switch:$false'
Test-SwitchParam -Switch:$false
'$Params = @{Switch = $true}; Test-SwitchParam @Params'
$Params = @{Switch = $true}; Test-SwitchParam @Params
'$Params = @{Switch = $false}; Test-SwitchParam @Params'
$Params = @{Switch = $false}; Test-SwitchParam @ParamsTest-SwitchParam
Switch: False
Switch.IsPresent: False
Test-SwitchParam -Switch
Switch: True
Switch.IsPresent: True
Test-SwitchParam -Switch:$true
Switch: True
Switch.IsPresent: True
Test-SwitchParam -Switch:$false
Switch: False
Switch.IsPresent: False
$Params = @{Switch = $true}; Test-SwitchParam @Params
Switch: True
Switch.IsPresent: True
$Params = @{Switch = $false}; Test-SwitchParam @Params
Switch: False
Switch.IsPresent: False
I think we should remove
NoTypeInformationeverywhere in code and leave only its declaration - the parameter is dummy and we should ignore it in code at all.
I'm torn on that. It's still an active parameter and setting it still has impact and will continue to do so. It's just hidden in favor of the new switch to make the new default behavior more clear. The internal logic would all need to be reworked. I didn't see value in switching all the logic to use IncludeTypeInformation when all that needs to be done is the upfront logic of detecting if both were supplied and setting NoTypeInformation based on the presence and setting of -IncludeTypeInformation. The logic would still need to be there, so why disturb the rest of the code for it?
for clarity: -NoTypeInformation:$false -NoTypeInformation:$true are both still valid.
There was a problem hiding this comment.
I see - somebody can use -NoTypeInformation:$false.
However, I think we should make the code simpler and more readable. Currently -IncludeTypeInformation:$false don't work. I vote for removing many private variables and using IsPresent.
There was a problem hiding this comment.
Currently -IncludeTypeInformation:$false don't work
It does currently work, that's not new functionality. The decision by the committee was to maintain that functionality. This is how we preserve that functionality while adding a new parameter that is basically a reverse switch for the existing one. You can't move to IsPresent without breaking current functionality.
There was a problem hiding this comment.
@iSazonov I think I can make us both happy using this.MyInvocation.BoundParameters.ContainsKey(). I'll work on it.
There was a problem hiding this comment.
After nice walking and good dinner I was ready to agree with you 😄
|
|
||
| It "Should output an array of objects" { | ||
| $result = $testObject | ConvertTo-Csv | ||
| $result = $testObject | ConvertTo-Csv -IncludeTypeInformation |
There was a problem hiding this comment.
I believe we shouldn't add -IncludeTypeInformation in tests where we don't check ""#TYPE ".
There was a problem hiding this comment.
Ah, I miss understood what this one was testing. I will fix it.
| It "Includes type information when -IncludeTypeInformation is supplied" { | ||
| $result = $testObject | ConvertTo-Csv -IncludeTypeInformation | ||
|
|
||
| ($result -split ([Environment]::NewLine))[0] | Should BeExactly "#TYPE System.Management.Automation.PSCustomObject" |
There was a problem hiding this comment.
I think we need add reverse test to check that ""#TYPE " is absent if -IncludeTypeInformation is absent.
Also that -NoTypeInformation do nothing.
There was a problem hiding this comment.
sure I'll add those and do the same for the Export-Csv tests
| /// </summary> | ||
| protected override void BeginProcessing() | ||
| { | ||
| if (this.MyInvocation.BoundParameters.ContainsKey("IncludeTypeInformation") && this.MyInvocation.BoundParameters.ContainsKey("NoTypeInformation")) |
There was a problem hiding this comment.
Interesting, can we replace the string names with strong typed names?
What about different parameter sets?
There was a problem hiding this comment.
can we replace the string names with strong typed names?
I'm not sure I understand what you are asking. IncludeTypeInformation.GetType().Name instead of "IncludeTypeInformation"?
What about different parameter sets?
parameter sets wont work without creating a bunch more. The parameter sets are currently being used for culture vs delimiter. It would get messy and harder to maintain than a logic check, IMO.
There was a problem hiding this comment.
In the future, we need to revisit how to make defining and reading mutual exclusion of parameters easier. Using multiple parametersets today can be quite complex to get right. For now, having a runtime check is ok.
There was a problem hiding this comment.
@SteveL-MSFT I created #5175 to track/discuss mutually exclusive parameters from a general position.
There was a problem hiding this comment.
I meant something like nameof(param1).
| $result[0] | Should Be "#TYPE System.Management.Automation.PSCustomObject" | ||
| } | ||
|
|
||
| It "Should return the column info in the second element of the output array" { |
There was a problem hiding this comment.
We could remove the test - it is dup test in line 28.
Or it is better move the checks and next test to the test in line 28 - there we can check a type, a header and data.
It is minor comment.
There was a problem hiding this comment.
@iSazonov Which test do you want to remove? the one you comment is on (lin 58) is not a duplicate of any of the tests. Line 28 is a delimiter test which needs to remain as its a different logic gate (parameter set).
the test on line 52 is now redundant with the the test on line 84, though.
There was a problem hiding this comment.
It seems we could try to refactor the tests but not in the PR.
So skip the minor comment.
| protected override void BeginProcessing() | ||
| { | ||
| if (this.MyInvocation.BoundParameters.ContainsKey("IncludeTypeInformation") && this.MyInvocation.BoundParameters.ContainsKey("NoTypeInformation")) | ||
| if (this.MyInvocation.BoundParameters.ContainsKey(nameof(IncludeTypeInformation)) && this.MyInvocation.BoundParameters.ContainsKey(nameof(NoTypeInformation))) |
There was a problem hiding this comment.
Can we use different parameter sets to exclude the code?
There was a problem hiding this comment.
@iSazonov we already discussed that here
The parameter sets are currently being used for delimiter vs culture. That would require we add 2 more parameter sets. It would make the code harder to maintain. The parameter sets would be confusing to the user because we are hiding -NoTypeInformation with DontShow=true. @SteveL-MSFT agreed that the runtime check was fine for now until we could address the larger general problem of mutex parameters. which prompted issue #5175
closes #5131
-NoTypeInformationas the default behavior forExport-CsvandConvertTo-Csv-NoTypeInformationparameter switch-IncludeTypeInformationswitch toExport-CsvandConvertTo-Csvto enable legacy behavior-NoTypeInformationand-IncludeTypeInformationare suppliedBreaking change was approved by committee in #5131
The new behavior will need to be documented.