schemez 0.2.4__py3-none-any.whl → 0.3.0__py3-none-any.whl

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.
schemez/__init__.py CHANGED
@@ -1,5 +1,20 @@
1
- __version__ = "0.2.4"
1
+ """Schemez: main package.
2
2
 
3
+ Pydantic shim for config stuff.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from importlib.metadata import version
9
+
10
+ __version__ = version("schemez")
11
+ __title__ = "Schemez"
12
+
13
+ __author__ = "Philipp Temminghoff"
14
+ __author_email__ = "philipptemminghoff@googlemail.com"
15
+ __copyright__ = "Copyright (c) 2025 Philipp Temminghoff"
16
+ __license__ = "MIT"
17
+ __url__ = "https://github.com/phil65/schemez"
3
18
 
4
19
  from schemez.schema import Schema
5
20
  from schemez.code import PythonCode, JSONCode, TOMLCode, YAMLCode
@@ -11,6 +26,8 @@ from schemez.schemadef.schemadef import (
11
26
  )
12
27
  from schemez.pydantic_types import ModelIdentifier, ModelTemperature, MimeType
13
28
 
29
+ __version__ = version("schemez")
30
+
14
31
  __all__ = [
15
32
  "ImportedSchemaDef",
16
33
  "InlineSchemaDef",
schemez/pydantic_types.py CHANGED
@@ -2,9 +2,13 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Annotated, Any
5
+ from typing import TYPE_CHECKING, Annotated, Any
6
6
 
7
- from pydantic import BaseModel, Field
7
+ from pydantic import Field
8
+
9
+
10
+ if TYPE_CHECKING:
11
+ from pydantic import BaseModel
8
12
 
9
13
 
10
14
  ModelIdentifier = Annotated[
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  from enum import Enum
6
6
  from typing import Annotated, Any, Literal
7
7
 
8
- from pydantic import BaseModel, Field, create_model
8
+ from pydantic import BaseModel, Field, create_model, field_validator
9
9
 
10
10
  from schemez import Schema, helpers
11
11
 
@@ -18,6 +18,7 @@ class SchemaField(Schema):
18
18
  - Optional description
19
19
  - Validation constraints
20
20
  - Enum values (when type is 'enum')
21
+ - Field dependencies and relationships
21
22
 
22
23
  Used by InlineSchemaDef to structure response fields.
23
24
  """
@@ -31,7 +32,6 @@ class SchemaField(Schema):
31
32
  values: list[Any] | None = None
32
33
  """Values for enum type fields"""
33
34
 
34
- # Common validation constraints
35
35
  default: Any | None = None
36
36
  """Default value for the field"""
37
37
 
@@ -41,10 +41,10 @@ class SchemaField(Schema):
41
41
  pattern: str | None = None
42
42
  """Regex pattern for string validation"""
43
43
 
44
- min_length: int | None = None
44
+ min_length: Annotated[int | None, Field(ge=0)] = None
45
45
  """Minimum length for collections"""
46
46
 
47
- max_length: int | None = None
47
+ max_length: Annotated[int | None, Field(ge=0)] = None
48
48
  """Maximum length for collections"""
49
49
 
50
50
  gt: float | None = None
@@ -59,7 +59,7 @@ class SchemaField(Schema):
59
59
  le: float | None = None
60
60
  """Less than or equal (inclusive) validation for numbers"""
61
61
 
62
- multiple_of: float | None = None
62
+ multiple_of: Annotated[float | None, Field(gt=0)] = None
63
63
  """Number must be a multiple of this value"""
64
64
 
65
65
  literal_value: Any | None = None
@@ -77,10 +77,55 @@ class SchemaField(Schema):
77
77
  field_config: dict[str, Any] | None = None
78
78
  """Configuration for Pydantic model fields"""
79
79
 
80
+ # Dependencies between fields
81
+ dependent_required: dict[str, list[str]] = Field(default_factory=dict)
82
+ """Field dependencies - when this field exists, dependent fields are required"""
83
+
84
+ dependent_schema: dict[str, dict[str, Any]] = Field(default_factory=dict)
85
+ """Schema dependencies - when this field exists, dependent fields must match schema"""
86
+
80
87
  # Extensibility for future or custom constraints
81
88
  constraints: dict[str, Any] = Field(default_factory=dict)
82
89
  """Additional constraints not covered by explicit fields"""
83
90
 
91
+ def add_required_dependency(
92
+ self, field_name: str, required_fields: list[str]
93
+ ) -> None:
94
+ """Add a dependency requiring other fields when this field exists.
95
+
96
+ Args:
97
+ field_name: The field that triggers the dependency
98
+ required_fields: Fields that become required when field_name exists
99
+ """
100
+ if field_name not in self.dependent_required:
101
+ self.dependent_required[field_name] = []
102
+ self.dependent_required[field_name].extend([
103
+ field
104
+ for field in required_fields
105
+ if field not in self.dependent_required[field_name]
106
+ ])
107
+
108
+ def add_schema_dependency(self, field_name: str, schema: dict[str, Any]) -> None:
109
+ """Add a schema dependency when this field exists.
110
+
111
+ Args:
112
+ field_name: The field that triggers the dependency
113
+ schema: JSON Schema to apply when field_name exists
114
+ """
115
+ self.dependent_schema[field_name] = schema
116
+
117
+ @field_validator("max_length")
118
+ @classmethod
119
+ def validate_max_min_length(cls, v: int | None, info) -> int | None:
120
+ if (
121
+ v is not None
122
+ and info.data.get("min_length") is not None
123
+ and v < info.data.get("min_length")
124
+ ):
125
+ msg = "max_length must be ≥ min_length"
126
+ raise ValueError(msg)
127
+ return v
128
+
84
129
 
85
130
  class BaseSchemaDef(Schema):
86
131
  """Base class for response definitions."""
@@ -98,14 +143,21 @@ class InlineSchemaDef(BaseSchemaDef):
98
143
  - Field definitions with types and descriptions
99
144
  - Optional validation constraints
100
145
  - Custom field descriptions
146
+ - Field dependencies and relationships
101
147
 
102
148
  Example:
103
- schemas:
104
- BasicResult:
105
- type: inline
106
- fields:
107
- success: {type: bool, description: "Operation success"}
108
- message: {type: str, description: "Result details"}
149
+ type: inline
150
+ fields:
151
+ success: {type: bool, description: "Operation success"}
152
+ message: {type: str, description: "Result details"}
153
+ payment_method: {type: str, description: "Payment method used"}
154
+ card_number: {
155
+ type: str,
156
+ description: "Credit card number",
157
+ dependent_required: {
158
+ "payment_method": ["card_expiry", "card_cvc"]
159
+ }
160
+ }
109
161
  """
110
162
 
111
163
  type: Literal["inline"] = Field("inline", init=False)
@@ -114,12 +166,49 @@ class InlineSchemaDef(BaseSchemaDef):
114
166
  fields: dict[str, SchemaField]
115
167
  """A dictionary containing all fields."""
116
168
 
169
+ def add_field_dependency(
170
+ self, field_name: str, dependent_on: str, required_fields: list[str]
171
+ ) -> None:
172
+ """Add a dependency between fields.
173
+
174
+ Args:
175
+ field_name: The field where to add the dependency
176
+ dependent_on: The field that triggers the dependency
177
+ required_fields: Fields that become required when the dependency is triggered
178
+ """
179
+ if field_name not in self.fields:
180
+ msg = f"Field '{field_name}' not found in schema"
181
+ raise ValueError(msg)
182
+
183
+ field = self.fields[field_name]
184
+ field.add_required_dependency(dependent_on, required_fields)
185
+
186
+ def add_schema_dependency(
187
+ self, field_name: str, dependent_on: str, schema: dict[str, Any]
188
+ ) -> None:
189
+ """Add a schema dependency between fields.
190
+
191
+ Args:
192
+ field_name: The field where to add the dependency
193
+ dependent_on: The field that triggers the dependency
194
+ schema: JSON Schema to apply when dependent_on exists
195
+ """
196
+ if field_name not in self.fields:
197
+ msg = f"Field '{field_name}' not found in schema"
198
+ raise ValueError(msg)
199
+
200
+ field = self.fields[field_name]
201
+ field.add_schema_dependency(dependent_on, schema)
202
+
117
203
  def get_schema(self) -> type[BaseModel]: # type: ignore
118
204
  """Create Pydantic model from inline definition."""
119
205
  fields = {}
206
+ model_dependencies: dict[str, dict[str, Any]] = {}
207
+
208
+ # First pass: collect all field information
120
209
  for name, field in self.fields.items():
121
210
  # Initialize constraint dictionary
122
- field_constraints = {}
211
+ field_constraints: dict[str, Any] = {}
123
212
 
124
213
  # Handle enum type
125
214
  if field.type == "enum":
@@ -203,20 +292,82 @@ class InlineSchemaDef(BaseSchemaDef):
203
292
  if field.json_schema_extra:
204
293
  field_constraints["json_schema_extra"] = field.json_schema_extra
205
294
 
295
+ # Handle field dependencies
296
+ if field.dependent_required or field.dependent_schema:
297
+ if field.json_schema_extra is None:
298
+ field_constraints["json_schema_extra"] = {}
299
+
300
+ json_extra = field_constraints.get("json_schema_extra", {})
301
+
302
+ if field.dependent_required:
303
+ if "dependentRequired" not in json_extra:
304
+ json_extra["dependentRequired"] = {}
305
+ json_extra["dependentRequired"].update(field.dependent_required)
306
+
307
+ if field.dependent_schema:
308
+ if "dependentSchemas" not in json_extra:
309
+ json_extra["dependentSchemas"] = {}
310
+ json_extra["dependentSchemas"].update(field.dependent_schema)
311
+
312
+ field_constraints["json_schema_extra"] = json_extra
313
+
206
314
  # Add any additional constraints
207
315
  field_constraints.update(field.constraints)
208
316
 
209
317
  field_info = Field(description=field.description, **field_constraints)
210
318
  fields[name] = (python_type, field_info)
211
319
 
320
+ # Collect model-level dependencies for JSON Schema
321
+ if field.dependent_required or field.dependent_schema:
322
+ if not model_dependencies:
323
+ model_dependencies = {"json_schema_extra": {}}
324
+
325
+ if field.dependent_required:
326
+ if "dependentRequired" not in model_dependencies["json_schema_extra"]:
327
+ model_dependencies["json_schema_extra"]["dependentRequired"] = {}
328
+ model_dependencies["json_schema_extra"]["dependentRequired"].update(
329
+ field.dependent_required
330
+ )
331
+
332
+ if field.dependent_schema:
333
+ if "dependentSchemas" not in model_dependencies["json_schema_extra"]:
334
+ model_dependencies["json_schema_extra"]["dependentSchemas"] = {}
335
+ model_dependencies["json_schema_extra"]["dependentSchemas"].update(
336
+ field.dependent_schema
337
+ )
338
+
339
+ # Create the model class with field definitions
212
340
  cls_name = self.description or "ResponseType"
213
- return create_model(
341
+ model = create_model(
214
342
  cls_name,
215
343
  **fields,
216
344
  __base__=BaseModel,
217
345
  __doc__=self.description,
218
346
  ) # type: ignore[call-overload]
219
347
 
348
+ # Add model-level JSON Schema extras for dependencies
349
+ if model_dependencies:
350
+ if not hasattr(model, "model_config") or not model.model_config:
351
+ model.model_config = {}
352
+
353
+ if "json_schema_extra" not in model.model_config:
354
+ model.model_config["json_schema_extra"] = {}
355
+
356
+ schema_extra = model.model_config["json_schema_extra"]
357
+
358
+ if "dependentRequired" in model_dependencies["json_schema_extra"]:
359
+ schema_extra["dependentRequired"] = model_dependencies[
360
+ "json_schema_extra"
361
+ ]["dependentRequired"]
362
+
363
+ if "dependentSchemas" in model_dependencies["json_schema_extra"]:
364
+ schema_extra["dependentSchemas"] = model_dependencies[
365
+ "json_schema_extra"
366
+ ]["dependentSchemas"]
367
+
368
+ # Return the created model
369
+ return model
370
+
220
371
 
221
372
  class ImportedSchemaDef(BaseSchemaDef):
222
373
  """Response definition that imports an existing Pydantic model.
@@ -1,36 +1,32 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.3
2
2
  Name: schemez
3
- Version: 0.2.4
3
+ Version: 0.3.0
4
4
  Summary: Pydantic shim for config stuff
5
- Project-URL: Documentation, https://phil65.github.io/schemez/
6
- Project-URL: Source, https://github.com/phil65/schemez
7
- Project-URL: Issues, https://github.com/phil65/schemez/issues
8
- Project-URL: Discussions, https://github.com/phil65/schemez/discussions
9
- Project-URL: Code coverage, https://app.codecov.io/gh/phil65/schemez
5
+ Keywords:
6
+ Author: Philipp Temminghoff
10
7
  Author-email: Philipp Temminghoff <philipptemminghoff@googlemail.com>
11
8
  License: MIT License
12
-
13
- Copyright (c) 2024, Philipp Temminghoff
14
-
15
- Permission is hereby granted, free of charge, to any person obtaining a copy
16
- of this software and associated documentation files (the "Software"), to deal
17
- in the Software without restriction, including without limitation the rights
18
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
- copies of the Software, and to permit persons to whom the Software is
20
- furnished to do so, subject to the following conditions:
21
-
22
- The above copyright notice and this permission notice shall be included in all
23
- copies or substantial portions of the Software.
24
-
25
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
- SOFTWARE.
32
-
33
- License-File: LICENSE
9
+
10
+ Copyright (c) 2024, Philipp Temminghoff
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+
34
30
  Classifier: Development Status :: 4 - Beta
35
31
  Classifier: Framework :: Pydantic
36
32
  Classifier: Framework :: Pydantic :: 2
@@ -45,23 +41,26 @@ Classifier: Topic :: Documentation
45
41
  Classifier: Topic :: Software Development
46
42
  Classifier: Topic :: Utilities
47
43
  Classifier: Typing :: Typed
48
- Requires-Python: >=3.12
49
44
  Requires-Dist: griffe>=1.7.3
50
45
  Requires-Dist: pydantic
51
46
  Requires-Dist: universal-pathlib>=0.2.6
47
+ Requires-Dist: llmling-agent ; extra == 'ai'
48
+ Requires-Dist: anyenv>=0.4.14 ; extra == 'ai'
49
+ Requires-Dist: yamling ; extra == 'yaml'
50
+ Requires-Python: >=3.12
51
+ Project-URL: Code coverage, https://app.codecov.io/gh/phil65/schemez
52
+ Project-URL: Discussions, https://github.com/phil65/schemez/discussions
53
+ Project-URL: Documentation, https://phil65.github.io/schemez/
54
+ Project-URL: Issues, https://github.com/phil65/schemez/issues
55
+ Project-URL: Source, https://github.com/phil65/schemez
52
56
  Provides-Extra: ai
53
- Requires-Dist: anyenv>=0.4.14; extra == 'ai'
54
- Requires-Dist: llmling-agent; extra == 'ai'
55
57
  Provides-Extra: yaml
56
- Requires-Dist: yamling; extra == 'yaml'
57
58
  Description-Content-Type: text/markdown
58
59
 
59
60
  # Schemez
60
61
 
61
62
  [![PyPI License](https://img.shields.io/pypi/l/schemez.svg)](https://pypi.org/project/schemez/)
62
63
  [![Package status](https://img.shields.io/pypi/status/schemez.svg)](https://pypi.org/project/schemez/)
63
- [![Daily downloads](https://img.shields.io/pypi/dd/schemez.svg)](https://pypi.org/project/schemez/)
64
- [![Weekly downloads](https://img.shields.io/pypi/dw/schemez.svg)](https://pypi.org/project/schemez/)
65
64
  [![Monthly downloads](https://img.shields.io/pypi/dm/schemez.svg)](https://pypi.org/project/schemez/)
66
65
  [![Distribution format](https://img.shields.io/pypi/format/schemez.svg)](https://pypi.org/project/schemez/)
67
66
  [![Wheel availability](https://img.shields.io/pypi/wheel/schemez.svg)](https://pypi.org/project/schemez/)
@@ -79,12 +78,8 @@ Description-Content-Type: text/markdown
79
78
  [![Github last commit](https://img.shields.io/github/last-commit/phil65/schemez)](https://github.com/phil65/schemez/commits)
80
79
  [![Github release date](https://img.shields.io/github/release-date/phil65/schemez)](https://github.com/phil65/schemez/releases)
81
80
  [![Github language count](https://img.shields.io/github/languages/count/phil65/schemez)](https://github.com/phil65/schemez)
82
- [![Github commits this week](https://img.shields.io/github/commit-activity/w/phil65/schemez)](https://github.com/phil65/schemez)
83
81
  [![Github commits this month](https://img.shields.io/github/commit-activity/m/phil65/schemez)](https://github.com/phil65/schemez)
84
- [![Github commits this year](https://img.shields.io/github/commit-activity/y/phil65/schemez)](https://github.com/phil65/schemez)
85
82
  [![Package status](https://codecov.io/gh/phil65/schemez/branch/main/graph/badge.svg)](https://codecov.io/gh/phil65/schemez/)
86
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
87
83
  [![PyUp](https://pyup.io/repos/github/phil65/schemez/shield.svg)](https://pyup.io/repos/github/phil65/schemez/)
88
84
 
89
85
  [Read the documentation!](https://phil65.github.io/schemez/)
90
-
@@ -0,0 +1,13 @@
1
+ schemez/__init__.py,sha256=iDo1ZpV07BUOmRmISV6QDA8s3viJR5V1NnrBsdw6eVM,985
2
+ schemez/code.py,sha256=usZLov9i5KpK1W2VJxngUzeetgrINtodiooG_AxN-y4,2072
3
+ schemez/convert.py,sha256=b6Sz11lq0HvpXfMREOqnnw8rcVg2XzTKhjjPNc4YIoE,4403
4
+ schemez/docstrings.py,sha256=kmd660wcomXzKac0SSNYxPRNbVCUovrpmE9jwnVRS6c,4115
5
+ schemez/helpers.py,sha256=Ee3wvFbt65ljhWDFdb6ACVUJK4KLjJFVzl4Le75pOBQ,5159
6
+ schemez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ schemez/pydantic_types.py,sha256=8vgSl8i2z9n0fB-8AJj-D3TBByEWE5IxItBxQ0XwXFI,1640
8
+ schemez/schema.py,sha256=VeNSFec6aCR9GgqXLBE3t4TZeUoS9BDmIoofe9nbqVI,8804
9
+ schemez/schemadef/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ schemez/schemadef/schemadef.py,sha256=m4m6f24xEgJgkp7jhp-6TpfLcwkVLL3WmKF9zDRhwAM,15091
11
+ schemez-0.3.0.dist-info/WHEEL,sha256=n2u5OFBbdZvCiUKAmfnY1Po2j3FB_NWfuUlt5WiAjrk,79
12
+ schemez-0.3.0.dist-info/METADATA,sha256=IQqDc_jIBQ8BepGQ3uRT_1FKNg21x-tLKzqbXUE5b90,5359
13
+ schemez-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.8.23
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -1,14 +0,0 @@
1
- schemez/__init__.py,sha256=q23JyNo20vslOAU0BXRZkfYba4iLGMSMQ7zs7t-4oFA,565
2
- schemez/code.py,sha256=usZLov9i5KpK1W2VJxngUzeetgrINtodiooG_AxN-y4,2072
3
- schemez/convert.py,sha256=b6Sz11lq0HvpXfMREOqnnw8rcVg2XzTKhjjPNc4YIoE,4403
4
- schemez/docstrings.py,sha256=kmd660wcomXzKac0SSNYxPRNbVCUovrpmE9jwnVRS6c,4115
5
- schemez/helpers.py,sha256=Ee3wvFbt65ljhWDFdb6ACVUJK4KLjJFVzl4Le75pOBQ,5159
6
- schemez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- schemez/pydantic_types.py,sha256=iiaHqVkWVd1TZry933aDYJnyzMD0HJIABfROR9txxhA,1581
8
- schemez/schema.py,sha256=VeNSFec6aCR9GgqXLBE3t4TZeUoS9BDmIoofe9nbqVI,8804
9
- schemez/schemadef/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- schemez/schemadef/schemadef.py,sha256=LTl6aRS-xovwUv-HWQ7UMZk_k4Jg9MjzVTpZswUplIE,8674
11
- schemez-0.2.4.dist-info/METADATA,sha256=1SjSzieIJhza0YqDjjrOaTRBtDmUWjs9JR5wq1AzMnc,5891
12
- schemez-0.2.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
- schemez-0.2.4.dist-info/licenses/LICENSE,sha256=AteGCH9r177TxxrOFEiOARrastASsf7yW6MQxlAHdwA,1078
14
- schemez-0.2.4.dist-info/RECORD,,
@@ -1,4 +0,0 @@
1
- Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
3
- Root-Is-Purelib: true
4
- Tag: py3-none-any
@@ -1,22 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024, Philipp Temminghoff
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.
22
-