Skip to content

Commit 9664752

Browse files
Merge pull request #199 from gabriel-samfira/models
Major refactor - PSCustomObjects and powershell classes
2 parents 5c81e85 + 2c63ad6 commit 9664752

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+8243
-364
lines changed

.github/workflows/ci.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
strategy:
2020
fail-fast: false
2121
matrix:
22-
os: [windows-latest]
22+
os: [windows-2022, windows-latest]
2323

2424
steps:
2525
- uses: actions/checkout@v3
@@ -40,8 +40,8 @@ jobs:
4040
strategy:
4141
fail-fast: false
4242
matrix:
43-
os: [macos-latest, ubuntu-latest, windows-latest]
44-
43+
os: [macos-latest, ubuntu-latest, windows-2022, windows-latest]
44+
4545
steps:
4646
- uses: actions/checkout@v3
4747
- name: Install modules

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
src/obj
22
src/bin
3+
src/*/obj
4+
src/*/bin
5+
src/*/*/obj
6+
src/*/*/bin
7+
8+
# Test results
9+
TestResults*.xml

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The ```lib``` folder contains the YamlDotNet assemblies. They are not really req
88

99
## Installation
1010

11-
This module is available for installation via [Powershell Gallery](http://www.powershellgallery.com/). Simply run the following command:
11+
This module is available for installation via [Powershell Gallery](http://www.powershellgallery.com/).
1212

1313
```powershell
1414
Install-Module powershell-yaml

Tests/CaseSensitiveKeys.ps1

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2016-2026 Cloudbase Solutions Srl
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
using namespace PowerShellYaml
17+
18+
# Test class demonstrating YamlKey attribute for case-sensitive YAML keys
19+
# PowerShell class properties are case-insensitive, so we need the attribute
20+
# to distinguish between "Test" and "test" in the YAML
21+
class CaseSensitiveTest : YamlBase {
22+
[YamlKey("Test")]
23+
[string]$CapitalizedTest = ""
24+
25+
[YamlKey("test")]
26+
[int]$LowercaseTest = 0
27+
}
28+
29+
# Test class with mixed attribute and auto-conversion
30+
class MixedKeysTest : YamlBase {
31+
# Uses attribute
32+
[YamlKey("custom-key")]
33+
[string]$CustomProperty = ""
34+
35+
# Uses automatic PascalCase -> hyphenated-case conversion
36+
[int]$AutoConvertedKey = 0
37+
}
38+
39+
# Test class that will fail due to duplicate key without explicit mapping
40+
class IWillFailDueToDuplicateKey : YamlBase {
41+
[string]$test = ""
42+
}
43+
44+
# Test class that succeeds because all duplicate keys are explicitly mapped
45+
class IWillSucceedBecauseIHaveAMappedKey : YamlBase {
46+
[YamlKey("test")]
47+
[string]$test = ""
48+
49+
[YamlKey("Test")]
50+
[string]$alsoTestButUppercase = ""
51+
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#!/usr/bin/env pwsh
2+
# Copyright 2016-2026 Cloudbase Solutions Srl
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
# Test classes for deep nesting with custom converters
17+
18+
using namespace PowerShellYaml
19+
using namespace System
20+
using namespace System.Collections.Generic
21+
22+
# Custom type: IP Address (renamed to avoid conflict with System.Net.IPAddress)
23+
class CustomIPAddress {
24+
[byte]$Octet1 = 0
25+
[byte]$Octet2 = 0
26+
[byte]$Octet3 = 0
27+
[byte]$Octet4 = 0
28+
29+
CustomIPAddress() {
30+
$this.Octet1 = 0
31+
$this.Octet2 = 0
32+
$this.Octet3 = 0
33+
$this.Octet4 = 0
34+
}
35+
36+
[string] ToString() {
37+
return "$($this.Octet1).$($this.Octet2).$($this.Octet3).$($this.Octet4)"
38+
}
39+
}
40+
41+
# Custom converter for IP Address
42+
class IPAddressConverter : YamlConverter {
43+
[bool] CanHandle([string]$tag, [Type]$targetType) {
44+
return $targetType -eq [CustomIPAddress]
45+
}
46+
47+
[object] ConvertFromYaml([object]$data, [string]$tag, [Type]$targetType) {
48+
$ip = [CustomIPAddress]@{}
49+
50+
if ($data -is [string]) {
51+
# Parse string format: "192.168.1.1"
52+
$octets = $data -split '\.'
53+
if ($octets.Length -ne 4) {
54+
throw [FormatException]::new("Invalid IP address format: $data")
55+
}
56+
$ip.Octet1 = [byte]$octets[0]
57+
$ip.Octet2 = [byte]$octets[1]
58+
$ip.Octet3 = [byte]$octets[2]
59+
$ip.Octet4 = [byte]$octets[3]
60+
}
61+
elseif ($data -is [System.Collections.Generic.Dictionary[string, object]]) {
62+
# Parse dictionary format
63+
if ($data.ContainsKey('a')) { $ip.Octet1 = [byte]$data['a'] }
64+
if ($data.ContainsKey('b')) { $ip.Octet2 = [byte]$data['b'] }
65+
if ($data.ContainsKey('c')) { $ip.Octet3 = [byte]$data['c'] }
66+
if ($data.ContainsKey('d')) { $ip.Octet4 = [byte]$data['d'] }
67+
}
68+
69+
return $ip
70+
}
71+
72+
[object] ConvertToYaml([object]$value) {
73+
$ip = [CustomIPAddress]$value
74+
return @{
75+
Value = $ip.ToString()
76+
Tag = '!ipaddr'
77+
}
78+
}
79+
}
80+
81+
# Custom type: Duration (simple time span)
82+
class Duration {
83+
[int]$Hours = 0
84+
[int]$Minutes = 0
85+
[int]$Seconds = 0
86+
87+
Duration() {
88+
$this.Hours = 0
89+
$this.Minutes = 0
90+
$this.Seconds = 0
91+
}
92+
93+
[string] ToString() {
94+
return "$($this.Hours)h$($this.Minutes)m$($this.Seconds)s"
95+
}
96+
}
97+
98+
# Custom converter for Duration
99+
class DurationConverter : YamlConverter {
100+
[bool] CanHandle([string]$tag, [Type]$targetType) {
101+
return $targetType -eq [Duration]
102+
}
103+
104+
[object] ConvertFromYaml([object]$data, [string]$tag, [Type]$targetType) {
105+
$duration = [Duration]::new()
106+
107+
if ($data -is [string]) {
108+
# Parse string format: "2h30m15s"
109+
if ($data -match '^(\d+)h(\d+)m(\d+)s$') {
110+
$duration.Hours = [int]$Matches[1]
111+
$duration.Minutes = [int]$Matches[2]
112+
$duration.Seconds = [int]$Matches[3]
113+
}
114+
else {
115+
throw [FormatException]::new("Invalid duration format: $data")
116+
}
117+
}
118+
elseif ($data -is [System.Collections.Generic.Dictionary[string, object]]) {
119+
if ($data.ContainsKey('hours')) { $duration.Hours = [int]$data['hours'] }
120+
if ($data.ContainsKey('minutes')) { $duration.Minutes = [int]$data['minutes'] }
121+
if ($data.ContainsKey('seconds')) { $duration.Seconds = [int]$data['seconds'] }
122+
}
123+
124+
return $duration
125+
}
126+
127+
[object] ConvertToYaml([object]$value) {
128+
$duration = [Duration]$value
129+
return @{
130+
Value = $duration.ToString()
131+
Tag = '!duration'
132+
}
133+
}
134+
}
135+
136+
# Level 3: Server configuration (deepest level with converters)
137+
class ServerConfig : YamlBase {
138+
[string]$Hostname = ""
139+
140+
[YamlConverter("IPAddressConverter")]
141+
[CustomIPAddress]$Address = $null
142+
143+
[int]$Port = 0
144+
145+
[YamlConverter("DurationConverter")]
146+
[Duration]$Timeout = $null
147+
}
148+
149+
# Level 2: Database configuration (middle level with converters)
150+
class DatabaseConfig : YamlBase {
151+
[string]$Name = ""
152+
153+
[YamlConverter("IPAddressConverter")]
154+
[CustomIPAddress]$Host = $null
155+
156+
[int]$Port = 0
157+
158+
[ServerConfig]$PrimaryServer = $null
159+
[ServerConfig]$ReplicaServer = $null
160+
161+
[YamlConverter("DurationConverter")]
162+
[Duration]$ConnectionTimeout = $null
163+
}
164+
165+
# Level 1: Application configuration (top level)
166+
class ApplicationConfig : YamlBase {
167+
[string]$AppName = ""
168+
[string]$Environment = ""
169+
170+
[DatabaseConfig]$Database = $null
171+
172+
[YamlConverter("IPAddressConverter")]
173+
[CustomIPAddress]$ApiGateway = $null
174+
175+
[YamlConverter("DurationConverter")]
176+
[Duration]$RequestTimeout = $null
177+
}

Tests/DeepNestingClasses.ps1

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2016-2026 Cloudbase Solutions Srl
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
using namespace PowerShellYaml
17+
18+
# Simple classes using default YamlBase implementations
19+
# No need to implement ToDictionary/FromDictionary!
20+
21+
class Person : YamlBase {
22+
[string]$Name = ""
23+
[int]$Age = 0
24+
}
25+
26+
class Family : YamlBase {
27+
[Person]$Mom = $null
28+
[Person]$Dad = $null
29+
[Person[]]$Children = $null
30+
}
31+
32+
class MyClass : YamlBase {
33+
[string]$Title = ""
34+
[Family]$Family = $null
35+
}

Tests/MappingStyleClasses.ps1

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env pwsh
2+
# Copyright 2016-2026 Cloudbase Solutions Srl
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
17+
using namespace PowerShellYaml
18+
19+
# Test classes for mapping style
20+
class Address : YamlBase {
21+
[string]$Street = ""
22+
[string]$City = ""
23+
[string]$Zip = ""
24+
}
25+
26+
class Person : YamlBase {
27+
[string]$Name = ""
28+
[int]$Age = 0
29+
[Address]$Address = $null
30+
}
31+
32+
class Company : YamlBase {
33+
[string]$Name = ""
34+
[Person]$Ceo = $null
35+
[Person[]]$Employees = @()
36+
}

Tests/TaggedScalars.ps1

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2016-2026 Cloudbase Solutions Srl
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
using namespace PowerShellYaml
17+
18+
# Test class for tagged scalar values
19+
class TaggedScalarsTest : YamlBase {
20+
[string]$StringValue = ""
21+
[int]$IntValue = 0
22+
}

0 commit comments

Comments
 (0)