ReadTheYAML 1.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. readtheyaml-1.9.0/LICENSE +21 -0
  2. readtheyaml-1.9.0/PKG-INFO +273 -0
  3. readtheyaml-1.9.0/README.md +261 -0
  4. readtheyaml-1.9.0/ReadTheYAML.egg-info/PKG-INFO +273 -0
  5. readtheyaml-1.9.0/ReadTheYAML.egg-info/SOURCES.txt +32 -0
  6. readtheyaml-1.9.0/ReadTheYAML.egg-info/dependency_links.txt +1 -0
  7. readtheyaml-1.9.0/ReadTheYAML.egg-info/requires.txt +1 -0
  8. readtheyaml-1.9.0/ReadTheYAML.egg-info/top_level.txt +4 -0
  9. readtheyaml-1.9.0/pyproject.toml +19 -0
  10. readtheyaml-1.9.0/readtheyaml/__init__.py +0 -0
  11. readtheyaml-1.9.0/readtheyaml/exceptions/__init__.py +0 -0
  12. readtheyaml-1.9.0/readtheyaml/exceptions/format_error.py +14 -0
  13. readtheyaml-1.9.0/readtheyaml/exceptions/validation_error.py +14 -0
  14. readtheyaml-1.9.0/readtheyaml/fields/__init__.py +0 -0
  15. readtheyaml-1.9.0/readtheyaml/fields/bool_field.py +21 -0
  16. readtheyaml-1.9.0/readtheyaml/fields/composite_field.py +27 -0
  17. readtheyaml-1.9.0/readtheyaml/fields/enum_field.py +16 -0
  18. readtheyaml-1.9.0/readtheyaml/fields/field.py +39 -0
  19. readtheyaml-1.9.0/readtheyaml/fields/field_helpers.py +109 -0
  20. readtheyaml-1.9.0/readtheyaml/fields/field_registery.py +21 -0
  21. readtheyaml-1.9.0/readtheyaml/fields/field_validation_helpers.py +35 -0
  22. readtheyaml-1.9.0/readtheyaml/fields/list_field.py +48 -0
  23. readtheyaml-1.9.0/readtheyaml/fields/none_field.py +13 -0
  24. readtheyaml-1.9.0/readtheyaml/fields/numerical_field.py +41 -0
  25. readtheyaml-1.9.0/readtheyaml/fields/string_field.py +45 -0
  26. readtheyaml-1.9.0/readtheyaml/fields/tuple_field.py +40 -0
  27. readtheyaml-1.9.0/readtheyaml/fields/union_field.py +56 -0
  28. readtheyaml-1.9.0/readtheyaml/schema.py +93 -0
  29. readtheyaml-1.9.0/readtheyaml/sections.py +96 -0
  30. readtheyaml-1.9.0/setup.cfg +4 -0
  31. readtheyaml-1.9.0/tests/__init__.py +0 -0
  32. readtheyaml-1.9.0/tests/test_composite_fields.py +898 -0
  33. readtheyaml-1.9.0/tests/test_fields.py +1159 -0
  34. readtheyaml-1.9.0/tests/test_schema.py +111 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Vincent Martineau
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,273 @@
1
+ Metadata-Version: 2.4
2
+ Name: ReadTheYAML
3
+ Version: 1.9.0
4
+ Summary: Validate and document your YAML config files — so future-you doesn't have to guess.
5
+ Author-email: Vincent Martineau <vincent.martineau.1@ulaval.ca>
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: pyyaml>=6.0
11
+ Dynamic: license-file
12
+
13
+ # ReadTheYaml
14
+
15
+ > A lightweight YAML schema validator with just enough structure to stop future-you from asking: "Why the heck did I set this to 42?"
16
+
17
+ ## What is this?
18
+
19
+ **ReadTheYaml** is a Python library that helps you define, validate, and document your YAML configuration files. It was built by someone (me) who got tired of forgetting:
20
+
21
+ - Which config values were required vs optional
22
+ - Why a given field was there in the first place
23
+ - What values are valid
24
+
25
+ It enforces structure in your YAML and documents everything along the way.
26
+
27
+ There might be more mature alternatives out there (really!), but this one's small, readable, and purpose-built for when you're tired of guessing your own project settings.
28
+
29
+ ---
30
+
31
+ ## 📦 Installation
32
+
33
+ ```bash
34
+ pip install ReadTheYaml
35
+ ```
36
+
37
+ Alternatively, clone the repo and install locally:
38
+
39
+ ```bash
40
+ git clone https://github.com/TheRealMarVin/ReadTheYaml.git
41
+ cd ReadTheYaml
42
+ pip install -e .
43
+ ```
44
+
45
+ ---
46
+
47
+ ## What can it do?
48
+
49
+ ### 🔹 Validate YAML config files
50
+ It ensures all required fields are present, types are correct, and defaults are filled in where needed.
51
+
52
+ ### 🔹 Support optional and required fields with descriptions
53
+ So future-you (or teammates) know what a setting is for.
54
+
55
+ ### 🔹 Provide default values
56
+ Optional fields can define a default that will be added if missing.
57
+
58
+ ### 🔹 Define valid numeric or length ranges
59
+ So you don’t accidentally open port `99999` or supply an empty list.
60
+
61
+ ### 🔹 Support list validation
62
+ You can define `list(int)`, `list(str)`, or even `list(nested(...))` to validate list content with precision.
63
+
64
+ ### 🔹 Define enum fields
65
+ You can restrict values to a fixed set of strings using `EnumField` or `type: enum`.
66
+
67
+ ### 🔹 Modular design with `$ref`
68
+ Schemas can include and reuse other schemas stored in separate files.
69
+
70
+ ---
71
+ ## Supported Schema Types
72
+
73
+ ReadTheYAML provides a flexible and expressive way to define and validate data structures using YAML. Below is an overview of the supported types, their syntax, and usage examples. I tried to follow the standard of type hints in Python, but I relaxed some constraints.
74
+
75
+ ### 🔹 Basic Types
76
+
77
+ * `None`: Represents None.
78
+ * `int`: Represents integer values.
79
+ * `float`: Represents floating-point numbers.
80
+ * `str`: Represents string values.
81
+ * `bool`: Represents boolean values (`true` or `false`).
82
+
83
+ **Example:**
84
+
85
+ ```yaml
86
+ type: int
87
+ ```
88
+
89
+ ### 🔹 Composite Types
90
+
91
+ #### List
92
+
93
+ Defines a list of elements of a specified type.
94
+
95
+ **Syntax:**
96
+
97
+ ```yaml
98
+ type: list[<element_type>]
99
+ ```
100
+
101
+ **Example:**
102
+
103
+ ```yaml
104
+ type: list[int]
105
+ ```
106
+
107
+ #### Tuple
108
+
109
+ Defines a fixed-size sequence of elements, each with a specified type.
110
+
111
+ **Syntax:**
112
+
113
+ ```yaml
114
+ type: tuple[<type1>, <type2>, ...]
115
+ ```
116
+
117
+ **Example:**
118
+
119
+ ```yaml
120
+ type: tuple[int, str]
121
+ ```
122
+
123
+ #### Union
124
+
125
+ Specifies that a value can be of one of several types.
126
+
127
+ **Syntax:**
128
+
129
+ ```yaml
130
+ type: union[<type1>, <type2>, ...]
131
+ ```
132
+
133
+ **Example:**
134
+
135
+ ```yaml
136
+ type: union[int, str]
137
+ ```
138
+
139
+ ### 🔹 Optional Types
140
+
141
+ To indicate that a field is optional (i.e., it can be `null`), include `None` in a `union`.
142
+
143
+ **Example:**
144
+
145
+ ```yaml
146
+ type: union[int, None]
147
+ ```
148
+
149
+ Alternatively, you can use the shorthand:
150
+
151
+ ```yaml
152
+ type: int | None
153
+ ```
154
+
155
+ ### 🔹 Syntax Variations
156
+
157
+ ReadTheYAML supports both square brackets `[]` and parentheses `()` for defining composite types. However, the opening and closing brackets must match.
158
+
159
+ **Valid:**
160
+
161
+ ```yaml
162
+ type: tuple[int, str]
163
+ type: tuple(int, str)
164
+ ```
165
+
166
+ **Invalid:**
167
+
168
+ ```yaml
169
+ type: tuple[int, str)
170
+ type: tuple(int, str]
171
+ ```
172
+
173
+ ### 🔹 Nested Types
174
+
175
+ You can nest composite types to define complex structures.
176
+
177
+ **Example:**
178
+
179
+ ```yaml
180
+ type: list[tuple[int, str]]
181
+ ```
182
+
183
+ This defines a list where each element is a tuple containing an integer and a string.
184
+
185
+ ### 🔹 Field Options
186
+
187
+ Fields can have additional options to control validation and behavior:
188
+
189
+ * `description`: Provides a human-readable description of the field. This one is mandatory
190
+ * `required`: Indicates whether the field is mandatory. By default, the value is false (the field is not required).
191
+ * `default`: Specifies a default value if the field is omitted. This is mandatory when required is set to false.
192
+
193
+
194
+ **Example:**
195
+
196
+ ```yaml
197
+ name:
198
+ type: str
199
+ required: true
200
+ default: Unnamed
201
+ description: The name of the entity.
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Example schema.yaml
207
+
208
+ ```yaml
209
+ name: app_config
210
+
211
+ status:
212
+ type: enum
213
+ enum: [pending, approved, rejected]
214
+ required: true
215
+
216
+ retries:
217
+ type: int
218
+ default: 3
219
+ min_value: 0
220
+ max_value: 10
221
+
222
+ servers:
223
+ type: list(nested(Server))
224
+ length_range: [1, 5]
225
+
226
+ tags:
227
+ type: list(str)
228
+ min_length: 1
229
+
230
+ Server:
231
+ host:
232
+ type: str
233
+ required: true
234
+ port:
235
+ type: int
236
+ default: 8080
237
+ min_value: 1
238
+ max_value: 65535
239
+ ```
240
+
241
+ ---
242
+
243
+ ## How to Use
244
+
245
+ ### 1. Validate a file with CLI
246
+ ```bash
247
+ python -m ReadTheYaml.cli --schema schema.yaml --config config.yaml
248
+ ```
249
+
250
+ You’ll see:
251
+ ```
252
+ ✅ Config is valid!
253
+ ```
254
+
255
+ Or, if something’s off:
256
+ ```
257
+ ❌ Validation failed: [status] must be one of: pending, approved, rejected
258
+ ```
259
+
260
+ ### 2. Programmatic usage
261
+ ```python
262
+ from readtheyaml.schema import Schema
263
+
264
+ try:
265
+ schema = Schema.from_yaml("schema.yaml")
266
+ validated_config = schema.validate_file("config.yaml")
267
+ print(validated_config)
268
+ except Exception as e:
269
+ print(f"⚠️ Failed to load or validate config: {e}")
270
+ ```
271
+ ---
272
+ ## Contributions
273
+ If you try this out and find something confusing or missing — feel free to open an issue or suggestion. This project is a work-in-progress, but built with love and frustration.
@@ -0,0 +1,261 @@
1
+ # ReadTheYaml
2
+
3
+ > A lightweight YAML schema validator with just enough structure to stop future-you from asking: "Why the heck did I set this to 42?"
4
+
5
+ ## What is this?
6
+
7
+ **ReadTheYaml** is a Python library that helps you define, validate, and document your YAML configuration files. It was built by someone (me) who got tired of forgetting:
8
+
9
+ - Which config values were required vs optional
10
+ - Why a given field was there in the first place
11
+ - What values are valid
12
+
13
+ It enforces structure in your YAML and documents everything along the way.
14
+
15
+ There might be more mature alternatives out there (really!), but this one's small, readable, and purpose-built for when you're tired of guessing your own project settings.
16
+
17
+ ---
18
+
19
+ ## 📦 Installation
20
+
21
+ ```bash
22
+ pip install ReadTheYaml
23
+ ```
24
+
25
+ Alternatively, clone the repo and install locally:
26
+
27
+ ```bash
28
+ git clone https://github.com/TheRealMarVin/ReadTheYaml.git
29
+ cd ReadTheYaml
30
+ pip install -e .
31
+ ```
32
+
33
+ ---
34
+
35
+ ## What can it do?
36
+
37
+ ### 🔹 Validate YAML config files
38
+ It ensures all required fields are present, types are correct, and defaults are filled in where needed.
39
+
40
+ ### 🔹 Support optional and required fields with descriptions
41
+ So future-you (or teammates) know what a setting is for.
42
+
43
+ ### 🔹 Provide default values
44
+ Optional fields can define a default that will be added if missing.
45
+
46
+ ### 🔹 Define valid numeric or length ranges
47
+ So you don’t accidentally open port `99999` or supply an empty list.
48
+
49
+ ### 🔹 Support list validation
50
+ You can define `list(int)`, `list(str)`, or even `list(nested(...))` to validate list content with precision.
51
+
52
+ ### 🔹 Define enum fields
53
+ You can restrict values to a fixed set of strings using `EnumField` or `type: enum`.
54
+
55
+ ### 🔹 Modular design with `$ref`
56
+ Schemas can include and reuse other schemas stored in separate files.
57
+
58
+ ---
59
+ ## Supported Schema Types
60
+
61
+ ReadTheYAML provides a flexible and expressive way to define and validate data structures using YAML. Below is an overview of the supported types, their syntax, and usage examples. I tried to follow the standard of type hints in Python, but I relaxed some constraints.
62
+
63
+ ### 🔹 Basic Types
64
+
65
+ * `None`: Represents None.
66
+ * `int`: Represents integer values.
67
+ * `float`: Represents floating-point numbers.
68
+ * `str`: Represents string values.
69
+ * `bool`: Represents boolean values (`true` or `false`).
70
+
71
+ **Example:**
72
+
73
+ ```yaml
74
+ type: int
75
+ ```
76
+
77
+ ### 🔹 Composite Types
78
+
79
+ #### List
80
+
81
+ Defines a list of elements of a specified type.
82
+
83
+ **Syntax:**
84
+
85
+ ```yaml
86
+ type: list[<element_type>]
87
+ ```
88
+
89
+ **Example:**
90
+
91
+ ```yaml
92
+ type: list[int]
93
+ ```
94
+
95
+ #### Tuple
96
+
97
+ Defines a fixed-size sequence of elements, each with a specified type.
98
+
99
+ **Syntax:**
100
+
101
+ ```yaml
102
+ type: tuple[<type1>, <type2>, ...]
103
+ ```
104
+
105
+ **Example:**
106
+
107
+ ```yaml
108
+ type: tuple[int, str]
109
+ ```
110
+
111
+ #### Union
112
+
113
+ Specifies that a value can be of one of several types.
114
+
115
+ **Syntax:**
116
+
117
+ ```yaml
118
+ type: union[<type1>, <type2>, ...]
119
+ ```
120
+
121
+ **Example:**
122
+
123
+ ```yaml
124
+ type: union[int, str]
125
+ ```
126
+
127
+ ### 🔹 Optional Types
128
+
129
+ To indicate that a field is optional (i.e., it can be `null`), include `None` in a `union`.
130
+
131
+ **Example:**
132
+
133
+ ```yaml
134
+ type: union[int, None]
135
+ ```
136
+
137
+ Alternatively, you can use the shorthand:
138
+
139
+ ```yaml
140
+ type: int | None
141
+ ```
142
+
143
+ ### 🔹 Syntax Variations
144
+
145
+ ReadTheYAML supports both square brackets `[]` and parentheses `()` for defining composite types. However, the opening and closing brackets must match.
146
+
147
+ **Valid:**
148
+
149
+ ```yaml
150
+ type: tuple[int, str]
151
+ type: tuple(int, str)
152
+ ```
153
+
154
+ **Invalid:**
155
+
156
+ ```yaml
157
+ type: tuple[int, str)
158
+ type: tuple(int, str]
159
+ ```
160
+
161
+ ### 🔹 Nested Types
162
+
163
+ You can nest composite types to define complex structures.
164
+
165
+ **Example:**
166
+
167
+ ```yaml
168
+ type: list[tuple[int, str]]
169
+ ```
170
+
171
+ This defines a list where each element is a tuple containing an integer and a string.
172
+
173
+ ### 🔹 Field Options
174
+
175
+ Fields can have additional options to control validation and behavior:
176
+
177
+ * `description`: Provides a human-readable description of the field. This one is mandatory
178
+ * `required`: Indicates whether the field is mandatory. By default, the value is false (the field is not required).
179
+ * `default`: Specifies a default value if the field is omitted. This is mandatory when required is set to false.
180
+
181
+
182
+ **Example:**
183
+
184
+ ```yaml
185
+ name:
186
+ type: str
187
+ required: true
188
+ default: Unnamed
189
+ description: The name of the entity.
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Example schema.yaml
195
+
196
+ ```yaml
197
+ name: app_config
198
+
199
+ status:
200
+ type: enum
201
+ enum: [pending, approved, rejected]
202
+ required: true
203
+
204
+ retries:
205
+ type: int
206
+ default: 3
207
+ min_value: 0
208
+ max_value: 10
209
+
210
+ servers:
211
+ type: list(nested(Server))
212
+ length_range: [1, 5]
213
+
214
+ tags:
215
+ type: list(str)
216
+ min_length: 1
217
+
218
+ Server:
219
+ host:
220
+ type: str
221
+ required: true
222
+ port:
223
+ type: int
224
+ default: 8080
225
+ min_value: 1
226
+ max_value: 65535
227
+ ```
228
+
229
+ ---
230
+
231
+ ## How to Use
232
+
233
+ ### 1. Validate a file with CLI
234
+ ```bash
235
+ python -m ReadTheYaml.cli --schema schema.yaml --config config.yaml
236
+ ```
237
+
238
+ You’ll see:
239
+ ```
240
+ ✅ Config is valid!
241
+ ```
242
+
243
+ Or, if something’s off:
244
+ ```
245
+ ❌ Validation failed: [status] must be one of: pending, approved, rejected
246
+ ```
247
+
248
+ ### 2. Programmatic usage
249
+ ```python
250
+ from readtheyaml.schema import Schema
251
+
252
+ try:
253
+ schema = Schema.from_yaml("schema.yaml")
254
+ validated_config = schema.validate_file("config.yaml")
255
+ print(validated_config)
256
+ except Exception as e:
257
+ print(f"⚠️ Failed to load or validate config: {e}")
258
+ ```
259
+ ---
260
+ ## Contributions
261
+ If you try this out and find something confusing or missing — feel free to open an issue or suggestion. This project is a work-in-progress, but built with love and frustration.