createsonline 0.1.26__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.
Files changed (152) hide show
  1. createsonline/__init__.py +46 -0
  2. createsonline/admin/__init__.py +7 -0
  3. createsonline/admin/content.py +526 -0
  4. createsonline/admin/crud.py +805 -0
  5. createsonline/admin/field_builder.py +559 -0
  6. createsonline/admin/integration.py +482 -0
  7. createsonline/admin/interface.py +2562 -0
  8. createsonline/admin/model_creator.py +513 -0
  9. createsonline/admin/model_manager.py +388 -0
  10. createsonline/admin/modern_dashboard.py +498 -0
  11. createsonline/admin/permissions.py +264 -0
  12. createsonline/admin/user_forms.py +594 -0
  13. createsonline/ai/__init__.py +202 -0
  14. createsonline/ai/fields.py +1226 -0
  15. createsonline/ai/orm.py +325 -0
  16. createsonline/ai/services.py +1244 -0
  17. createsonline/app.py +506 -0
  18. createsonline/auth/__init__.py +8 -0
  19. createsonline/auth/management.py +228 -0
  20. createsonline/auth/models.py +552 -0
  21. createsonline/cli/__init__.py +5 -0
  22. createsonline/cli/commands/__init__.py +122 -0
  23. createsonline/cli/commands/database.py +416 -0
  24. createsonline/cli/commands/info.py +173 -0
  25. createsonline/cli/commands/initdb.py +218 -0
  26. createsonline/cli/commands/project.py +545 -0
  27. createsonline/cli/commands/serve.py +173 -0
  28. createsonline/cli/commands/shell.py +93 -0
  29. createsonline/cli/commands/users.py +148 -0
  30. createsonline/cli/main.py +2041 -0
  31. createsonline/cli/manage.py +274 -0
  32. createsonline/config/__init__.py +9 -0
  33. createsonline/config/app.py +2577 -0
  34. createsonline/config/database.py +179 -0
  35. createsonline/config/docs.py +384 -0
  36. createsonline/config/errors.py +160 -0
  37. createsonline/config/orm.py +43 -0
  38. createsonline/config/request.py +93 -0
  39. createsonline/config/settings.py +176 -0
  40. createsonline/data/__init__.py +23 -0
  41. createsonline/data/dataframe.py +925 -0
  42. createsonline/data/io.py +453 -0
  43. createsonline/data/series.py +557 -0
  44. createsonline/database/__init__.py +60 -0
  45. createsonline/database/abstraction.py +440 -0
  46. createsonline/database/assistant.py +585 -0
  47. createsonline/database/fields.py +442 -0
  48. createsonline/database/migrations.py +132 -0
  49. createsonline/database/models.py +604 -0
  50. createsonline/database.py +438 -0
  51. createsonline/http/__init__.py +28 -0
  52. createsonline/http/client.py +535 -0
  53. createsonline/ml/__init__.py +55 -0
  54. createsonline/ml/classification.py +552 -0
  55. createsonline/ml/clustering.py +680 -0
  56. createsonline/ml/metrics.py +542 -0
  57. createsonline/ml/neural.py +560 -0
  58. createsonline/ml/preprocessing.py +784 -0
  59. createsonline/ml/regression.py +501 -0
  60. createsonline/performance/__init__.py +19 -0
  61. createsonline/performance/cache.py +444 -0
  62. createsonline/performance/compression.py +335 -0
  63. createsonline/performance/core.py +419 -0
  64. createsonline/project_init.py +789 -0
  65. createsonline/routing.py +528 -0
  66. createsonline/security/__init__.py +34 -0
  67. createsonline/security/core.py +811 -0
  68. createsonline/security/encryption.py +349 -0
  69. createsonline/server.py +295 -0
  70. createsonline/static/css/admin.css +263 -0
  71. createsonline/static/css/common.css +358 -0
  72. createsonline/static/css/dashboard.css +89 -0
  73. createsonline/static/favicon.ico +0 -0
  74. createsonline/static/icons/icon-128x128.png +0 -0
  75. createsonline/static/icons/icon-128x128.webp +0 -0
  76. createsonline/static/icons/icon-16x16.png +0 -0
  77. createsonline/static/icons/icon-16x16.webp +0 -0
  78. createsonline/static/icons/icon-180x180.png +0 -0
  79. createsonline/static/icons/icon-180x180.webp +0 -0
  80. createsonline/static/icons/icon-192x192.png +0 -0
  81. createsonline/static/icons/icon-192x192.webp +0 -0
  82. createsonline/static/icons/icon-256x256.png +0 -0
  83. createsonline/static/icons/icon-256x256.webp +0 -0
  84. createsonline/static/icons/icon-32x32.png +0 -0
  85. createsonline/static/icons/icon-32x32.webp +0 -0
  86. createsonline/static/icons/icon-384x384.png +0 -0
  87. createsonline/static/icons/icon-384x384.webp +0 -0
  88. createsonline/static/icons/icon-48x48.png +0 -0
  89. createsonline/static/icons/icon-48x48.webp +0 -0
  90. createsonline/static/icons/icon-512x512.png +0 -0
  91. createsonline/static/icons/icon-512x512.webp +0 -0
  92. createsonline/static/icons/icon-64x64.png +0 -0
  93. createsonline/static/icons/icon-64x64.webp +0 -0
  94. createsonline/static/image/android-chrome-192x192.png +0 -0
  95. createsonline/static/image/android-chrome-512x512.png +0 -0
  96. createsonline/static/image/apple-touch-icon.png +0 -0
  97. createsonline/static/image/favicon-16x16.png +0 -0
  98. createsonline/static/image/favicon-32x32.png +0 -0
  99. createsonline/static/image/favicon.ico +0 -0
  100. createsonline/static/image/favicon.svg +17 -0
  101. createsonline/static/image/icon-128x128.png +0 -0
  102. createsonline/static/image/icon-128x128.webp +0 -0
  103. createsonline/static/image/icon-16x16.png +0 -0
  104. createsonline/static/image/icon-16x16.webp +0 -0
  105. createsonline/static/image/icon-180x180.png +0 -0
  106. createsonline/static/image/icon-180x180.webp +0 -0
  107. createsonline/static/image/icon-192x192.png +0 -0
  108. createsonline/static/image/icon-192x192.webp +0 -0
  109. createsonline/static/image/icon-256x256.png +0 -0
  110. createsonline/static/image/icon-256x256.webp +0 -0
  111. createsonline/static/image/icon-32x32.png +0 -0
  112. createsonline/static/image/icon-32x32.webp +0 -0
  113. createsonline/static/image/icon-384x384.png +0 -0
  114. createsonline/static/image/icon-384x384.webp +0 -0
  115. createsonline/static/image/icon-48x48.png +0 -0
  116. createsonline/static/image/icon-48x48.webp +0 -0
  117. createsonline/static/image/icon-512x512.png +0 -0
  118. createsonline/static/image/icon-512x512.webp +0 -0
  119. createsonline/static/image/icon-64x64.png +0 -0
  120. createsonline/static/image/icon-64x64.webp +0 -0
  121. createsonline/static/image/logo-header-h100.png +0 -0
  122. createsonline/static/image/logo-header-h100.webp +0 -0
  123. createsonline/static/image/logo-header-h200@2x.png +0 -0
  124. createsonline/static/image/logo-header-h200@2x.webp +0 -0
  125. createsonline/static/image/logo.png +0 -0
  126. createsonline/static/js/admin.js +274 -0
  127. createsonline/static/site.webmanifest +35 -0
  128. createsonline/static/templates/admin/base.html +87 -0
  129. createsonline/static/templates/admin/dashboard.html +217 -0
  130. createsonline/static/templates/admin/model_form.html +270 -0
  131. createsonline/static/templates/admin/model_list.html +202 -0
  132. createsonline/static/test_script.js +15 -0
  133. createsonline/static/test_styles.css +59 -0
  134. createsonline/static_files.py +365 -0
  135. createsonline/templates/404.html +100 -0
  136. createsonline/templates/admin_login.html +169 -0
  137. createsonline/templates/base.html +102 -0
  138. createsonline/templates/index.html +151 -0
  139. createsonline/templates.py +205 -0
  140. createsonline/testing.py +322 -0
  141. createsonline/utils.py +448 -0
  142. createsonline/validation/__init__.py +49 -0
  143. createsonline/validation/fields.py +598 -0
  144. createsonline/validation/models.py +504 -0
  145. createsonline/validation/validators.py +561 -0
  146. createsonline/views.py +184 -0
  147. createsonline-0.1.26.dist-info/METADATA +46 -0
  148. createsonline-0.1.26.dist-info/RECORD +152 -0
  149. createsonline-0.1.26.dist-info/WHEEL +5 -0
  150. createsonline-0.1.26.dist-info/entry_points.txt +2 -0
  151. createsonline-0.1.26.dist-info/licenses/LICENSE +21 -0
  152. createsonline-0.1.26.dist-info/top_level.txt +1 -0
@@ -0,0 +1,504 @@
1
+ """
2
+ CREATESONLINE Validation Models
3
+
4
+ Pure Python model validation.
5
+ Lightweight replacement for Pydantic BaseModel.
6
+ """
7
+
8
+ import json
9
+ import sys
10
+ from typing import Any, Dict, List, Optional, Type, Union
11
+ from .fields import Field
12
+ from .validators import ValidationError
13
+
14
+ # Handle typing compatibility across Python versions
15
+ if sys.version_info >= (3, 10):
16
+ from typing import get_type_hints
17
+ else:
18
+ try:
19
+ from typing import get_type_hints
20
+ except ImportError:
21
+ def get_type_hints(obj):
22
+ return getattr(obj, '__annotations__', {})
23
+
24
+
25
+ class ModelMeta(type):
26
+ """Metaclass for BaseModel to collect field definitions"""
27
+
28
+ def __new__(mcs, name, bases, namespace, **kwargs):
29
+ # Collect fields from the class definition
30
+ fields = {}
31
+
32
+ # Inherit fields from base classes
33
+ for base in bases:
34
+ if hasattr(base, '_fields'):
35
+ fields.update(base._fields)
36
+
37
+ # Add fields from current class
38
+ for key, value in list(namespace.items()):
39
+ if isinstance(value, Field):
40
+ fields[key] = value
41
+ # Remove field from namespace to avoid conflicts
42
+ namespace.pop(key)
43
+
44
+ # Create the class
45
+ cls = super().__new__(mcs, name, bases, namespace)
46
+
47
+ # Store fields on the class
48
+ cls._fields = fields
49
+
50
+ # Store field names for easier access
51
+ cls._field_names = list(fields.keys())
52
+
53
+ return cls
54
+
55
+
56
+ class BaseModel(metaclass=ModelMeta):
57
+ """
58
+ Base model class for data validation
59
+
60
+ Pure Python implementation similar to Pydantic BaseModel.
61
+ """
62
+
63
+ _fields: Dict[str, Field] = {}
64
+ _field_names: List[str] = []
65
+
66
+ def __init__(self, **data):
67
+ """
68
+ Initialize model with data validation
69
+
70
+ Args:
71
+ **data: Data to validate and assign
72
+ """
73
+ self._validated_data = {}
74
+ self._errors = {}
75
+
76
+ # Process each field
77
+ for field_name, field in self._fields.items():
78
+ # Check for alias
79
+ data_key = field.alias if field.alias else field_name
80
+
81
+ # Get value from data
82
+ if data_key in data:
83
+ value = data[data_key]
84
+ elif field.default is not None:
85
+ value = field.default
86
+ elif not field.required:
87
+ value = None
88
+ else:
89
+ self._errors[field_name] = "Field is required"
90
+ continue
91
+
92
+ # Validate field
93
+ try:
94
+ validated_value = field.validate(value, field_name)
95
+ self._validated_data[field_name] = validated_value
96
+ # Set as attribute for easy access
97
+ setattr(self, field_name, validated_value)
98
+ except ValidationError as e:
99
+ self._errors[field_name] = str(e)
100
+
101
+ # Check for unknown fields
102
+ known_keys = set(field.alias if field.alias else name for name, field in self._fields.items())
103
+ unknown_keys = set(data.keys()) - known_keys
104
+ if unknown_keys:
105
+ for key in unknown_keys:
106
+ self._errors[key] = f"Unknown field: {key}"
107
+
108
+ # Raise validation error if there are any errors
109
+ if self._errors:
110
+ raise ValidationError(f"Validation failed: {self._errors}")
111
+
112
+ @classmethod
113
+ def validate(cls, data: Union[Dict[str, Any], 'BaseModel']) -> 'BaseModel':
114
+ """
115
+ Validate data and return model instance
116
+
117
+ Args:
118
+ data: Data to validate (dict or BaseModel)
119
+
120
+ Returns:
121
+ Validated model instance
122
+
123
+ Raises:
124
+ ValidationError: If validation fails
125
+ """
126
+ if isinstance(data, cls):
127
+ return data
128
+ elif isinstance(data, dict):
129
+ return cls(**data)
130
+ else:
131
+ raise ValidationError("Data must be a dictionary or model instance")
132
+
133
+ @classmethod
134
+ def parse_obj(cls, obj: Dict[str, Any]) -> 'BaseModel':
135
+ """
136
+ Parse object (alias for validate)
137
+
138
+ Args:
139
+ obj: Object to parse
140
+
141
+ Returns:
142
+ Validated model instance
143
+ """
144
+ return cls.validate(obj)
145
+
146
+ @classmethod
147
+ def parse_raw(cls, raw_data: Union[str, bytes], content_type: str = 'json') -> 'BaseModel':
148
+ """
149
+ Parse raw data (JSON, etc.)
150
+
151
+ Args:
152
+ raw_data: Raw data to parse
153
+ content_type: Content type ('json' supported)
154
+
155
+ Returns:
156
+ Validated model instance
157
+ """
158
+ if content_type == 'json':
159
+ if isinstance(raw_data, bytes):
160
+ raw_data = raw_data.decode('utf-8')
161
+
162
+ try:
163
+ data = json.loads(raw_data)
164
+ return cls.validate(data)
165
+ except json.JSONDecodeError as e:
166
+ raise ValidationError(f"Invalid JSON: {e}")
167
+ else:
168
+ raise ValidationError(f"Unsupported content type: {content_type}")
169
+
170
+ @classmethod
171
+ def parse_file(cls, file_path: str, content_type: str = 'json', encoding: str = 'utf-8') -> 'BaseModel':
172
+ """
173
+ Parse data from file
174
+
175
+ Args:
176
+ file_path: Path to file
177
+ content_type: Content type ('json' supported)
178
+ encoding: File encoding
179
+
180
+ Returns:
181
+ Validated model instance
182
+ """
183
+ try:
184
+ with open(file_path, 'r', encoding=encoding) as f:
185
+ raw_data = f.read()
186
+ return cls.parse_raw(raw_data, content_type)
187
+ except IOError as e:
188
+ raise ValidationError(f"Error reading file: {e}")
189
+
190
+ def dict(
191
+ self,
192
+ include: Optional[Union[List[str], set]] = None,
193
+ exclude: Optional[Union[List[str], set]] = None,
194
+ by_alias: bool = False
195
+ ) -> Dict[str, Any]:
196
+ """
197
+ Convert model to dictionary
198
+
199
+ Args:
200
+ include: Fields to include
201
+ exclude: Fields to exclude
202
+ by_alias: Use field aliases as keys
203
+
204
+ Returns:
205
+ Dictionary representation
206
+ """
207
+ result = {}
208
+
209
+ for field_name, value in self._validated_data.items():
210
+ # Check include/exclude filters
211
+ if include is not None and field_name not in include:
212
+ continue
213
+ if exclude is not None and field_name in exclude:
214
+ continue
215
+
216
+ # Use alias if requested and available
217
+ if by_alias and field_name in self._fields:
218
+ field = self._fields[field_name]
219
+ key = field.alias if field.alias else field_name
220
+ else:
221
+ key = field_name
222
+
223
+ result[key] = value
224
+
225
+ return result
226
+
227
+ def json(
228
+ self,
229
+ include: Optional[Union[List[str], set]] = None,
230
+ exclude: Optional[Union[List[str], set]] = None,
231
+ by_alias: bool = False,
232
+ indent: Optional[int] = None
233
+ ) -> str:
234
+ """
235
+ Convert model to JSON string
236
+
237
+ Args:
238
+ include: Fields to include
239
+ exclude: Fields to exclude
240
+ by_alias: Use field aliases as keys
241
+ indent: JSON indentation
242
+
243
+ Returns:
244
+ JSON string representation
245
+ """
246
+ data = self.dict(include=include, exclude=exclude, by_alias=by_alias)
247
+ return json.dumps(data, indent=indent, default=str, ensure_ascii=False)
248
+
249
+ def copy(
250
+ self,
251
+ update: Optional[Dict[str, Any]] = None,
252
+ deep: bool = False
253
+ ) -> 'BaseModel':
254
+ """
255
+ Create a copy of the model
256
+
257
+ Args:
258
+ update: Fields to update in the copy
259
+ deep: Whether to perform deep copy
260
+
261
+ Returns:
262
+ Copied model instance
263
+ """
264
+ data = self.dict()
265
+
266
+ if update:
267
+ data.update(update)
268
+
269
+ if deep:
270
+ import copy
271
+ data = copy.deepcopy(data)
272
+
273
+ return self.__class__(**data)
274
+
275
+ def update(self, update_data: Dict[str, Any]) -> 'BaseModel':
276
+ """
277
+ Update model with new data
278
+
279
+ Args:
280
+ update_data: Data to update
281
+
282
+ Returns:
283
+ Updated model instance
284
+ """
285
+ current_data = self.dict()
286
+ current_data.update(update_data)
287
+ return self.__class__(**current_data)
288
+
289
+ @classmethod
290
+ def schema(cls, by_alias: bool = True) -> Dict[str, Any]:
291
+ """
292
+ Generate JSON schema for the model
293
+
294
+ Args:
295
+ by_alias: Use field aliases in schema
296
+
297
+ Returns:
298
+ JSON schema dictionary
299
+ """
300
+ properties = {}
301
+ required = []
302
+
303
+ for field_name, field in cls._fields.items():
304
+ # Use alias if requested and available
305
+ schema_name = field.alias if by_alias and field.alias else field_name
306
+
307
+ # Basic field schema
308
+ field_schema = {
309
+ 'type': cls._get_json_type(field),
310
+ 'description': field.description
311
+ }
312
+
313
+ # Add field-specific constraints
314
+ if hasattr(field, 'min_length') and field.min_length is not None:
315
+ field_schema['minLength'] = field.min_length
316
+ if hasattr(field, 'max_length') and field.max_length is not None:
317
+ field_schema['maxLength'] = field.max_length
318
+ if hasattr(field, 'min_value') and field.min_value is not None:
319
+ field_schema['minimum'] = field.min_value
320
+ if hasattr(field, 'max_value') and field.max_value is not None:
321
+ field_schema['maximum'] = field.max_value
322
+ if hasattr(field, 'pattern') and field.pattern is not None:
323
+ field_schema['pattern'] = field.pattern
324
+ if hasattr(field, 'choices') and field.choices is not None:
325
+ field_schema['enum'] = field.choices
326
+
327
+ # Default value
328
+ if field.default is not None:
329
+ field_schema['default'] = field.default
330
+
331
+ properties[schema_name] = field_schema
332
+
333
+ # Required fields
334
+ if field.required and field.default is None:
335
+ required.append(schema_name)
336
+
337
+ schema = {
338
+ 'type': 'object',
339
+ 'properties': properties,
340
+ 'title': cls.__name__
341
+ }
342
+
343
+ if required:
344
+ schema['required'] = required
345
+
346
+ return schema
347
+
348
+ @staticmethod
349
+ def _get_json_type(field: Field) -> str:
350
+ """Get JSON schema type for a field"""
351
+ from .fields import (
352
+ StringField, IntField, FloatField, BoolField,
353
+ EmailField, URLField, DateField, ListField, DictField
354
+ )
355
+
356
+ if isinstance(field, (StringField, EmailField, URLField, DateField)):
357
+ return 'string'
358
+ elif isinstance(field, IntField):
359
+ return 'integer'
360
+ elif isinstance(field, FloatField):
361
+ return 'number'
362
+ elif isinstance(field, BoolField):
363
+ return 'boolean'
364
+ elif isinstance(field, ListField):
365
+ return 'array'
366
+ elif isinstance(field, DictField):
367
+ return 'object'
368
+ else:
369
+ return 'string' # Default fallback
370
+
371
+ def __repr__(self) -> str:
372
+ """String representation of the model"""
373
+ fields_repr = ', '.join(f'{k}={v!r}' for k, v in self._validated_data.items())
374
+ return f'{self.__class__.__name__}({fields_repr})'
375
+
376
+ def __str__(self) -> str:
377
+ """String representation of the model"""
378
+ return self.__repr__()
379
+
380
+ def __eq__(self, other) -> bool:
381
+ """Check equality with another model"""
382
+ if not isinstance(other, self.__class__):
383
+ return False
384
+ return self._validated_data == other._validated_data
385
+
386
+ def __hash__(self) -> int:
387
+ """Hash of the model"""
388
+ return hash(tuple(sorted(self._validated_data.items())))
389
+
390
+ def __getitem__(self, item: str) -> Any:
391
+ """Get field value by name"""
392
+ if item in self._validated_data:
393
+ return self._validated_data[item]
394
+ raise KeyError(f"Field '{item}' not found")
395
+
396
+ def __setitem__(self, key: str, value: Any) -> None:
397
+ """Set field value (with validation)"""
398
+ if key in self._fields:
399
+ field = self._fields[key]
400
+ try:
401
+ validated_value = field.validate(value, key)
402
+ self._validated_data[key] = validated_value
403
+ setattr(self, key, validated_value)
404
+ except ValidationError as e:
405
+ raise ValidationError(f"Validation failed for field '{key}': {e}")
406
+ else:
407
+ raise KeyError(f"Unknown field '{key}'")
408
+
409
+ def __contains__(self, item: str) -> bool:
410
+ """Check if field exists"""
411
+ return item in self._validated_data
412
+
413
+ def __iter__(self):
414
+ """Iterate over field names"""
415
+ return iter(self._validated_data)
416
+
417
+ def keys(self):
418
+ """Get field names"""
419
+ return self._validated_data.keys()
420
+
421
+ def values(self):
422
+ """Get field values"""
423
+ return self._validated_data.values()
424
+
425
+ def items(self):
426
+ """Get field items"""
427
+ return self._validated_data.items()
428
+
429
+
430
+ # Utility functions for creating models dynamically
431
+ def create_model(
432
+ model_name: str,
433
+ fields: Dict[str, Field],
434
+ base_class: Type[BaseModel] = BaseModel
435
+ ) -> Type[BaseModel]:
436
+ """
437
+ Create a model class dynamically
438
+
439
+ Args:
440
+ model_name: Name of the model class
441
+ fields: Dictionary of field definitions
442
+ base_class: Base class to inherit from
443
+
444
+ Returns:
445
+ Dynamically created model class
446
+ """
447
+ # Create class attributes
448
+ attrs = dict(fields)
449
+ attrs['__module__'] = __name__
450
+
451
+ # Create the class
452
+ model_class = type(model_name, (base_class,), attrs)
453
+
454
+ return model_class
455
+
456
+
457
+ # Validation shortcuts
458
+ def validate_data(data: Dict[str, Any], fields: Dict[str, Field]) -> Dict[str, Any]:
459
+ """
460
+ Validate data against field definitions without creating a model
461
+
462
+ Args:
463
+ data: Data to validate
464
+ fields: Field definitions
465
+
466
+ Returns:
467
+ Validated data dictionary
468
+
469
+ Raises:
470
+ ValidationError: If validation fails
471
+ """
472
+ validated_data = {}
473
+ errors = {}
474
+
475
+ for field_name, field in fields.items():
476
+ # Get value from data
477
+ if field_name in data:
478
+ value = data[field_name]
479
+ elif field.default is not None:
480
+ value = field.default
481
+ elif not field.required:
482
+ value = None
483
+ else:
484
+ errors[field_name] = "Field is required"
485
+ continue
486
+
487
+ # Validate field
488
+ try:
489
+ validated_value = field.validate(value, field_name)
490
+ validated_data[field_name] = validated_value
491
+ except ValidationError as e:
492
+ errors[field_name] = str(e)
493
+
494
+ # Check for unknown fields
495
+ unknown_keys = set(data.keys()) - set(fields.keys())
496
+ if unknown_keys:
497
+ for key in unknown_keys:
498
+ errors[key] = f"Unknown field: {key}"
499
+
500
+ # Raise validation error if there are any errors
501
+ if errors:
502
+ raise ValidationError(f"Validation failed: {errors}")
503
+
504
+ return validated_data