string-schema 0.1.1__py3-none-any.whl → 0.1.3__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.
- string_schema/core/__init__.py +23 -0
- string_schema/core/builders.py +244 -0
- string_schema/core/fields.py +138 -0
- string_schema/core/validators.py +242 -0
- string_schema/examples/__init__.py +36 -0
- string_schema/examples/presets.py +345 -0
- string_schema/examples/recipes.py +380 -0
- string_schema/integrations/__init__.py +15 -0
- string_schema/integrations/json_schema.py +385 -0
- string_schema/integrations/openapi.py +484 -0
- string_schema/integrations/pydantic.py +662 -0
- string_schema/integrations/reverse.py +275 -0
- string_schema/parsing/__init__.py +16 -0
- string_schema/parsing/optimizer.py +246 -0
- string_schema/parsing/string_parser.py +703 -0
- string_schema/parsing/syntax.py +250 -0
- {string_schema-0.1.1.dist-info → string_schema-0.1.3.dist-info}/METADATA +2 -3
- string_schema-0.1.3.dist-info/RECORD +24 -0
- string_schema-0.1.1.dist-info/RECORD +0 -8
- {string_schema-0.1.1.dist-info → string_schema-0.1.3.dist-info}/WHEEL +0 -0
- {string_schema-0.1.1.dist-info → string_schema-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {string_schema-0.1.1.dist-info → string_schema-0.1.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Common schema patterns and recipes for Simple Schema
|
|
3
|
+
|
|
4
|
+
Contains reusable patterns and helper functions for creating complex schemas.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, List, Optional, Union
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
from ..core.fields import SimpleField
|
|
11
|
+
from ..core.builders import simple_schema, list_of_objects_schema, simple_array_schema
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_list_schema(item_fields: Dict[str, Union[str, SimpleField]],
|
|
17
|
+
description: str = "List of items",
|
|
18
|
+
min_items: Optional[int] = None,
|
|
19
|
+
max_items: Optional[int] = None) -> Dict[str, Any]:
|
|
20
|
+
"""
|
|
21
|
+
Create a schema for a list of objects.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
item_fields: Field definitions for each item in the list
|
|
25
|
+
description: Description of the list
|
|
26
|
+
min_items: Minimum number of items
|
|
27
|
+
max_items: Maximum number of items
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
JSON Schema for list of objects
|
|
31
|
+
"""
|
|
32
|
+
return list_of_objects_schema(item_fields, description, min_items, max_items)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def create_nested_schema(base_fields: Dict[str, Union[str, SimpleField]],
|
|
36
|
+
nested_objects: Dict[str, Dict[str, Union[str, SimpleField]]]) -> Dict[str, Any]:
|
|
37
|
+
"""
|
|
38
|
+
Create a schema with nested objects.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
base_fields: Top-level field definitions
|
|
42
|
+
nested_objects: Dictionary of nested object definitions
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
JSON Schema with nested structure
|
|
46
|
+
"""
|
|
47
|
+
all_fields = base_fields.copy()
|
|
48
|
+
|
|
49
|
+
for nested_name, nested_fields in nested_objects.items():
|
|
50
|
+
# Create a nested object field
|
|
51
|
+
nested_schema = simple_schema(nested_fields)
|
|
52
|
+
# This is a simplified approach - in a full implementation,
|
|
53
|
+
# we'd need to handle this as a proper nested structure
|
|
54
|
+
all_fields[nested_name] = SimpleField('object', f'Nested {nested_name} object')
|
|
55
|
+
|
|
56
|
+
return simple_schema(all_fields)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def create_enum_schema(field_name: str,
|
|
60
|
+
values: List[str],
|
|
61
|
+
description: str = "",
|
|
62
|
+
required: bool = True) -> Dict[str, Any]:
|
|
63
|
+
"""
|
|
64
|
+
Create a schema with an enum field.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
field_name: Name of the enum field
|
|
68
|
+
values: List of allowed values
|
|
69
|
+
description: Field description
|
|
70
|
+
required: Whether the field is required
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
JSON Schema with enum field
|
|
74
|
+
"""
|
|
75
|
+
fields = {
|
|
76
|
+
field_name: SimpleField('string', description, required=required, choices=values)
|
|
77
|
+
}
|
|
78
|
+
return simple_schema(fields)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def create_union_schema(field_name: str,
|
|
82
|
+
types: List[str],
|
|
83
|
+
description: str = "",
|
|
84
|
+
required: bool = True) -> Dict[str, Any]:
|
|
85
|
+
"""
|
|
86
|
+
Create a schema with a union type field.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
field_name: Name of the union field
|
|
90
|
+
types: List of allowed types
|
|
91
|
+
description: Field description
|
|
92
|
+
required: Whether the field is required
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
JSON Schema with union field
|
|
96
|
+
"""
|
|
97
|
+
primary_type = types[0] if types else 'string'
|
|
98
|
+
fields = {
|
|
99
|
+
field_name: SimpleField(primary_type, description, required=required, union_types=types)
|
|
100
|
+
}
|
|
101
|
+
return simple_schema(fields)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def create_pagination_schema(item_fields: Dict[str, Union[str, SimpleField]],
|
|
105
|
+
include_metadata: bool = True) -> Dict[str, Any]:
|
|
106
|
+
"""
|
|
107
|
+
Create a paginated response schema.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
item_fields: Field definitions for each item
|
|
111
|
+
include_metadata: Whether to include pagination metadata
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
JSON Schema for paginated response
|
|
115
|
+
"""
|
|
116
|
+
fields = {
|
|
117
|
+
'items': SimpleField('array', 'List of items')
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if include_metadata:
|
|
121
|
+
fields.update({
|
|
122
|
+
'total': SimpleField('integer', 'Total number of items', min_val=0),
|
|
123
|
+
'page': SimpleField('integer', 'Current page number', min_val=1),
|
|
124
|
+
'per_page': SimpleField('integer', 'Items per page', min_val=1),
|
|
125
|
+
'has_next': SimpleField('boolean', 'Whether there are more pages'),
|
|
126
|
+
'has_prev': SimpleField('boolean', 'Whether there are previous pages')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
# Note: In a full implementation, we'd properly handle the nested array schema
|
|
130
|
+
return simple_schema(fields)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def create_api_response_schema(data_fields: Dict[str, Union[str, SimpleField]],
|
|
134
|
+
include_status: bool = True,
|
|
135
|
+
include_metadata: bool = False) -> Dict[str, Any]:
|
|
136
|
+
"""
|
|
137
|
+
Create a standard API response schema.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
data_fields: Field definitions for the data payload
|
|
141
|
+
include_status: Whether to include status information
|
|
142
|
+
include_metadata: Whether to include response metadata
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
JSON Schema for API response
|
|
146
|
+
"""
|
|
147
|
+
fields = {
|
|
148
|
+
'data': SimpleField('object', 'Response data payload')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if include_status:
|
|
152
|
+
fields.update({
|
|
153
|
+
'success': SimpleField('boolean', 'Whether the request was successful'),
|
|
154
|
+
'message': SimpleField('string', 'Response message', required=False)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
if include_metadata:
|
|
158
|
+
fields.update({
|
|
159
|
+
'timestamp': SimpleField('string', 'Response timestamp', format_hint='datetime'),
|
|
160
|
+
'request_id': SimpleField('string', 'Unique request identifier', format_hint='uuid', required=False)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
return simple_schema(fields)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def create_error_schema(include_details: bool = True) -> Dict[str, Any]:
|
|
167
|
+
"""
|
|
168
|
+
Create a standard error response schema.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
include_details: Whether to include detailed error information
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
JSON Schema for error response
|
|
175
|
+
"""
|
|
176
|
+
fields = {
|
|
177
|
+
'error': SimpleField('boolean', 'Error indicator', default=True),
|
|
178
|
+
'message': SimpleField('string', 'Error message'),
|
|
179
|
+
'code': SimpleField('string', 'Error code', required=False)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if include_details:
|
|
183
|
+
fields.update({
|
|
184
|
+
'details': SimpleField('string', 'Detailed error information', required=False),
|
|
185
|
+
'timestamp': SimpleField('string', 'Error timestamp', format_hint='datetime'),
|
|
186
|
+
'path': SimpleField('string', 'Request path that caused the error', required=False)
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
return simple_schema(fields)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def create_search_schema(result_fields: Dict[str, Union[str, SimpleField]],
|
|
193
|
+
include_facets: bool = False) -> Dict[str, Any]:
|
|
194
|
+
"""
|
|
195
|
+
Create a search results schema.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
result_fields: Field definitions for each search result
|
|
199
|
+
include_facets: Whether to include search facets
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
JSON Schema for search results
|
|
203
|
+
"""
|
|
204
|
+
fields = {
|
|
205
|
+
'query': SimpleField('string', 'Search query'),
|
|
206
|
+
'results': SimpleField('array', 'Search results'),
|
|
207
|
+
'total_results': SimpleField('integer', 'Total number of results', min_val=0),
|
|
208
|
+
'took': SimpleField('number', 'Search time in milliseconds', min_val=0, required=False)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if include_facets:
|
|
212
|
+
fields['facets'] = SimpleField('object', 'Search facets', required=False)
|
|
213
|
+
|
|
214
|
+
return simple_schema(fields)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def create_audit_schema(entity_fields: Dict[str, Union[str, SimpleField]]) -> Dict[str, Any]:
|
|
218
|
+
"""
|
|
219
|
+
Create an audit log schema.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
entity_fields: Field definitions for the audited entity
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
JSON Schema for audit log entry
|
|
226
|
+
"""
|
|
227
|
+
fields = {
|
|
228
|
+
'id': SimpleField('string', 'Audit log entry ID', format_hint='uuid'),
|
|
229
|
+
'entity_type': SimpleField('string', 'Type of entity being audited'),
|
|
230
|
+
'entity_id': SimpleField('string', 'ID of the audited entity'),
|
|
231
|
+
'action': SimpleField('string', 'Action performed',
|
|
232
|
+
choices=['create', 'update', 'delete', 'view']),
|
|
233
|
+
'user_id': SimpleField('string', 'ID of user who performed the action'),
|
|
234
|
+
'timestamp': SimpleField('string', 'When the action occurred', format_hint='datetime'),
|
|
235
|
+
'changes': SimpleField('object', 'What changed', required=False),
|
|
236
|
+
'metadata': SimpleField('object', 'Additional metadata', required=False)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return simple_schema(fields)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def create_notification_schema(include_delivery: bool = True) -> Dict[str, Any]:
|
|
243
|
+
"""
|
|
244
|
+
Create a notification schema.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
include_delivery: Whether to include delivery information
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
JSON Schema for notification
|
|
251
|
+
"""
|
|
252
|
+
fields = {
|
|
253
|
+
'id': SimpleField('string', 'Notification ID', format_hint='uuid'),
|
|
254
|
+
'type': SimpleField('string', 'Notification type',
|
|
255
|
+
choices=['info', 'warning', 'error', 'success']),
|
|
256
|
+
'title': SimpleField('string', 'Notification title', max_length=200),
|
|
257
|
+
'message': SimpleField('string', 'Notification message', max_length=1000),
|
|
258
|
+
'recipient_id': SimpleField('string', 'Recipient user ID'),
|
|
259
|
+
'created_at': SimpleField('string', 'Creation timestamp', format_hint='datetime'),
|
|
260
|
+
'read': SimpleField('boolean', 'Whether notification has been read', default=False)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if include_delivery:
|
|
264
|
+
fields.update({
|
|
265
|
+
'delivery_method': SimpleField('string', 'How notification was delivered',
|
|
266
|
+
choices=['email', 'sms', 'push', 'in_app'], required=False),
|
|
267
|
+
'delivered_at': SimpleField('string', 'Delivery timestamp',
|
|
268
|
+
format_hint='datetime', required=False)
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
return simple_schema(fields)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def create_file_metadata_schema(include_content_info: bool = True) -> Dict[str, Any]:
|
|
275
|
+
"""
|
|
276
|
+
Create a file metadata schema.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
include_content_info: Whether to include content analysis information
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
JSON Schema for file metadata
|
|
283
|
+
"""
|
|
284
|
+
fields = {
|
|
285
|
+
'filename': SimpleField('string', 'Original filename', max_length=255),
|
|
286
|
+
'size': SimpleField('integer', 'File size in bytes', min_val=0),
|
|
287
|
+
'mime_type': SimpleField('string', 'MIME type', max_length=100),
|
|
288
|
+
'uploaded_at': SimpleField('string', 'Upload timestamp', format_hint='datetime'),
|
|
289
|
+
'uploaded_by': SimpleField('string', 'User who uploaded the file'),
|
|
290
|
+
'checksum': SimpleField('string', 'File checksum (MD5/SHA256)', required=False)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if include_content_info:
|
|
294
|
+
fields.update({
|
|
295
|
+
'width': SimpleField('integer', 'Image width in pixels', min_val=0, required=False),
|
|
296
|
+
'height': SimpleField('integer', 'Image height in pixels', min_val=0, required=False),
|
|
297
|
+
'duration': SimpleField('number', 'Media duration in seconds', min_val=0, required=False),
|
|
298
|
+
'encoding': SimpleField('string', 'File encoding', required=False)
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
return simple_schema(fields)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def create_settings_schema(setting_groups: Dict[str, List[str]]) -> Dict[str, Any]:
|
|
305
|
+
"""
|
|
306
|
+
Create a user settings schema.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
setting_groups: Dictionary mapping group names to setting names
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
JSON Schema for user settings
|
|
313
|
+
"""
|
|
314
|
+
fields = {}
|
|
315
|
+
|
|
316
|
+
for group_name, setting_names in setting_groups.items():
|
|
317
|
+
for setting_name in setting_names:
|
|
318
|
+
# Create flexible setting fields that can hold various types
|
|
319
|
+
fields[f"{group_name}_{setting_name}"] = SimpleField(
|
|
320
|
+
'string', f'{group_name} {setting_name} setting', required=False
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
# Add common settings metadata
|
|
324
|
+
fields.update({
|
|
325
|
+
'user_id': SimpleField('string', 'User ID'),
|
|
326
|
+
'updated_at': SimpleField('string', 'Last update timestamp', format_hint='datetime'),
|
|
327
|
+
'version': SimpleField('integer', 'Settings version', min_val=1, default=1)
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
return simple_schema(fields)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
# Recipe combinations for common use cases
|
|
334
|
+
def create_ecommerce_product_schema() -> Dict[str, Any]:
|
|
335
|
+
"""Create a comprehensive e-commerce product schema"""
|
|
336
|
+
fields = {
|
|
337
|
+
'id': SimpleField('string', 'Product ID', format_hint='uuid'),
|
|
338
|
+
'sku': SimpleField('string', 'Stock keeping unit', max_length=50),
|
|
339
|
+
'name': SimpleField('string', 'Product name', min_length=1, max_length=200),
|
|
340
|
+
'description': SimpleField('string', 'Product description', max_length=2000, required=False),
|
|
341
|
+
'category': SimpleField('string', 'Product category',
|
|
342
|
+
choices=['electronics', 'clothing', 'books', 'home', 'sports']),
|
|
343
|
+
'price': SimpleField('number', 'Product price', min_val=0),
|
|
344
|
+
'currency': SimpleField('string', 'Price currency', choices=['USD', 'EUR', 'GBP'], default='USD'),
|
|
345
|
+
'in_stock': SimpleField('boolean', 'Whether product is in stock', default=True),
|
|
346
|
+
'stock_quantity': SimpleField('integer', 'Available quantity', min_val=0, required=False),
|
|
347
|
+
'weight': SimpleField('number', 'Product weight in kg', min_val=0, required=False),
|
|
348
|
+
'dimensions': SimpleField('string', 'Product dimensions', required=False),
|
|
349
|
+
'brand': SimpleField('string', 'Product brand', max_length=100, required=False),
|
|
350
|
+
'tags': SimpleField('string', 'Comma-separated tags', required=False),
|
|
351
|
+
'created_at': SimpleField('string', 'Creation timestamp', format_hint='datetime'),
|
|
352
|
+
'updated_at': SimpleField('string', 'Last update timestamp', format_hint='datetime')
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return simple_schema(fields)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def create_blog_post_schema() -> Dict[str, Any]:
|
|
359
|
+
"""Create a comprehensive blog post schema"""
|
|
360
|
+
fields = {
|
|
361
|
+
'id': SimpleField('string', 'Post ID', format_hint='uuid'),
|
|
362
|
+
'title': SimpleField('string', 'Post title', min_length=1, max_length=200),
|
|
363
|
+
'slug': SimpleField('string', 'URL slug', max_length=200),
|
|
364
|
+
'content': SimpleField('string', 'Post content', min_length=10),
|
|
365
|
+
'excerpt': SimpleField('string', 'Post excerpt', max_length=500, required=False),
|
|
366
|
+
'author_id': SimpleField('string', 'Author ID'),
|
|
367
|
+
'author_name': SimpleField('string', 'Author name', max_length=100),
|
|
368
|
+
'status': SimpleField('string', 'Post status',
|
|
369
|
+
choices=['draft', 'published', 'archived'], default='draft'),
|
|
370
|
+
'category': SimpleField('string', 'Post category', max_length=100, required=False),
|
|
371
|
+
'tags': SimpleField('string', 'Comma-separated tags', required=False),
|
|
372
|
+
'featured_image': SimpleField('string', 'Featured image URL', format_hint='url', required=False),
|
|
373
|
+
'published_at': SimpleField('string', 'Publication timestamp', format_hint='datetime', required=False),
|
|
374
|
+
'created_at': SimpleField('string', 'Creation timestamp', format_hint='datetime'),
|
|
375
|
+
'updated_at': SimpleField('string', 'Last update timestamp', format_hint='datetime'),
|
|
376
|
+
'view_count': SimpleField('integer', 'Number of views', min_val=0, default=0),
|
|
377
|
+
'comment_count': SimpleField('integer', 'Number of comments', min_val=0, default=0)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return simple_schema(fields)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Integrations module for String Schema
|
|
3
|
+
|
|
4
|
+
Contains integrations with external libraries and standards.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .pydantic import create_pydantic_model
|
|
8
|
+
from .json_schema import to_json_schema
|
|
9
|
+
from .openapi import to_openapi_schema
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"create_pydantic_model",
|
|
13
|
+
"to_json_schema",
|
|
14
|
+
"to_openapi_schema"
|
|
15
|
+
]
|