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,557 @@
1
+ """
2
+ CREATESONLINE Series Implementation
3
+
4
+ Pure Python series data structure.
5
+ Lightweight alternative to Pandas Series.
6
+ """
7
+
8
+ import json
9
+ from typing import Any, Dict, List, Optional, Union, Iterator, Callable
10
+
11
+ # Optional numpy import with fallback
12
+ try:
13
+ import numpy as np
14
+ NUMPY_AVAILABLE = True
15
+ NDArrayType = np.ndarray
16
+ except ImportError:
17
+ NUMPY_AVAILABLE = False
18
+ np = None
19
+ NDArrayType = Any # Fallback type
20
+
21
+
22
+ class CreatesonlineSeries:
23
+ """
24
+ CREATESONLINE Series - One-dimensional data structure
25
+
26
+ Pure Python implementation of a series data structure similar to Pandas Series
27
+ but with zero external dependencies (except numpy for numerical operations).
28
+ """
29
+
30
+ def __init__(
31
+ self,
32
+ data: Union[List[Any], Dict[str, Any]] = None,
33
+ index: Optional[List[str]] = None,
34
+ name: Optional[str] = None,
35
+ dtype: Optional[str] = None
36
+ ):
37
+ """
38
+ Initialize CREATESONLINE Series
39
+
40
+ Args:
41
+ data: Series data as list, array, or dict
42
+ index: Index labels for the data
43
+ name: Name of the series
44
+ dtype: Data type hint
45
+ """
46
+ self.name = name
47
+ self.dtype = dtype
48
+
49
+ if data is None:
50
+ self._data = []
51
+ self._index = []
52
+ elif isinstance(data, dict):
53
+ self._index = list(data.keys())
54
+ self._data = list(data.values())
55
+ elif isinstance(data, (list, tuple)):
56
+ self._data = list(data)
57
+ self._index = index or list(range(len(self._data)))
58
+ elif NUMPY_AVAILABLE and hasattr(data, 'tolist'): # numpy array
59
+ self._data = data.tolist()
60
+ self._index = index or list(range(len(self._data)))
61
+ else:
62
+ self._data = [data]
63
+ self._index = index or [0]
64
+
65
+ # Ensure index and data have same length
66
+ if len(self._index) != len(self._data):
67
+ if index is None:
68
+ self._index = list(range(len(self._data)))
69
+ else:
70
+ raise ValueError("Index length must match data length")
71
+
72
+ def __len__(self) -> int:
73
+ """Return length of series"""
74
+ return len(self._data)
75
+
76
+ def __getitem__(self, key: Union[str, int, slice, List[Union[str, int]]]) -> Union[Any, 'CreatesonlineSeries']:
77
+ """Get item(s) from series"""
78
+ if isinstance(key, (int, slice)):
79
+ if isinstance(key, slice):
80
+ return CreatesonlineSeries(
81
+ data=self._data[key],
82
+ index=self._index[key],
83
+ name=self.name
84
+ )
85
+ else:
86
+ return self._data[key]
87
+ elif isinstance(key, str):
88
+ if key in self._index:
89
+ idx = self._index.index(key)
90
+ return self._data[idx]
91
+ else:
92
+ raise KeyError(f"Key '{key}' not found in series")
93
+ elif isinstance(key, list):
94
+ result_data = []
95
+ result_index = []
96
+ for k in key:
97
+ if isinstance(k, str) and k in self._index:
98
+ idx = self._index.index(k)
99
+ result_data.append(self._data[idx])
100
+ result_index.append(k)
101
+ elif isinstance(k, int) and 0 <= k < len(self._data):
102
+ result_data.append(self._data[k])
103
+ result_index.append(self._index[k])
104
+ else:
105
+ raise KeyError(f"Key '{k}' not found in series")
106
+ return CreatesonlineSeries(
107
+ data=result_data,
108
+ index=result_index,
109
+ name=self.name
110
+ )
111
+ else:
112
+ raise TypeError(f"Invalid key type: {type(key)}")
113
+
114
+ def __setitem__(self, key: Union[str, int], value: Any):
115
+ """Set item in series"""
116
+ if isinstance(key, int):
117
+ if 0 <= key < len(self._data):
118
+ self._data[key] = value
119
+ else:
120
+ raise IndexError("Index out of range")
121
+ elif isinstance(key, str):
122
+ if key in self._index:
123
+ idx = self._index.index(key)
124
+ self._data[idx] = value
125
+ else:
126
+ # Add new item
127
+ self._index.append(key)
128
+ self._data.append(value)
129
+ else:
130
+ raise TypeError(f"Invalid key type: {type(key)}")
131
+
132
+ def __iter__(self) -> Iterator[Any]:
133
+ """Iterate over series values"""
134
+ return iter(self._data)
135
+
136
+ def __str__(self) -> str:
137
+ """String representation"""
138
+ lines = []
139
+ for i, (idx, val) in enumerate(zip(self._index, self._data)):
140
+ lines.append(f"{idx} {val}")
141
+ if i >= 20: # Limit display
142
+ lines.append("...")
143
+ break
144
+
145
+ if self.name:
146
+ lines.append(f"Name: {self.name}")
147
+
148
+ return "\n".join(lines)
149
+
150
+ def __repr__(self) -> str:
151
+ """String representation"""
152
+ return self.__str__()
153
+
154
+ @property
155
+ def values(self) -> List[Any]:
156
+ """Get series values as list"""
157
+ return self._data.copy()
158
+
159
+ @property
160
+ def index(self) -> List[str]:
161
+ """Get series index"""
162
+ return self._index.copy()
163
+
164
+ @property
165
+ def shape(self) -> tuple:
166
+ """Get series shape"""
167
+ return (len(self._data),)
168
+
169
+ @property
170
+ def size(self) -> int:
171
+ """Get series size"""
172
+ return len(self._data)
173
+
174
+ def head(self, n: int = 5) -> 'CreatesonlineSeries':
175
+ """Get first n elements"""
176
+ return self[:n]
177
+
178
+ def tail(self, n: int = 5) -> 'CreatesonlineSeries':
179
+ """Get last n elements"""
180
+ return self[-n:]
181
+
182
+ def copy(self) -> 'CreatesonlineSeries':
183
+ """Create a copy of the series"""
184
+ return CreatesonlineSeries(
185
+ data=self._data.copy(),
186
+ index=self._index.copy(),
187
+ name=self.name,
188
+ dtype=self.dtype
189
+ )
190
+
191
+ def reset_index(self, drop: bool = True) -> 'CreatesonlineSeries':
192
+ """Reset index to default integer index"""
193
+ if drop:
194
+ return CreatesonlineSeries(
195
+ data=self._data.copy(),
196
+ name=self.name,
197
+ dtype=self.dtype
198
+ )
199
+ else:
200
+ # Return DataFrame with old index as column
201
+ from .dataframe import CreatesonlineDataFrame
202
+ return CreatesonlineDataFrame({
203
+ 'index': self._index.copy(),
204
+ self.name or 'value': self._data.copy()
205
+ })
206
+
207
+ def sort_values(self, ascending: bool = True) -> 'CreatesonlineSeries':
208
+ """Sort series by values"""
209
+ paired = list(zip(self._data, self._index))
210
+ paired.sort(key=lambda x: x[0], reverse=not ascending)
211
+
212
+ sorted_data, sorted_index = zip(*paired)
213
+ return CreatesonlineSeries(
214
+ data=list(sorted_data),
215
+ index=list(sorted_index),
216
+ name=self.name,
217
+ dtype=self.dtype
218
+ )
219
+
220
+ def sort_index(self, ascending: bool = True) -> 'CreatesonlineSeries':
221
+ """Sort series by index"""
222
+ paired = list(zip(self._index, self._data))
223
+ paired.sort(key=lambda x: x[0], reverse=not ascending)
224
+
225
+ sorted_index, sorted_data = zip(*paired)
226
+ return CreatesonlineSeries(
227
+ data=list(sorted_data),
228
+ index=list(sorted_index),
229
+ name=self.name,
230
+ dtype=self.dtype
231
+ )
232
+
233
+ def unique(self) -> 'CreatesonlineSeries':
234
+ """Get unique values"""
235
+ seen = set()
236
+ unique_data = []
237
+ unique_index = []
238
+
239
+ for val, idx in zip(self._data, self._index):
240
+ if val not in seen:
241
+ seen.add(val)
242
+ unique_data.append(val)
243
+ unique_index.append(idx)
244
+
245
+ return CreatesonlineSeries(
246
+ data=unique_data,
247
+ index=unique_index,
248
+ name=self.name,
249
+ dtype=self.dtype
250
+ )
251
+
252
+ def value_counts(self) -> 'CreatesonlineSeries':
253
+ """Count occurrences of each value"""
254
+ counts = {}
255
+ for val in self._data:
256
+ counts[val] = counts.get(val, 0) + 1
257
+
258
+ return CreatesonlineSeries(
259
+ data=list(counts.values()),
260
+ index=list(counts.keys()),
261
+ name='count'
262
+ ).sort_values(ascending=False)
263
+
264
+ def apply(self, func: Callable[[Any], Any]) -> 'CreatesonlineSeries':
265
+ """Apply function to each element"""
266
+ new_data = [func(val) for val in self._data]
267
+ return CreatesonlineSeries(
268
+ data=new_data,
269
+ index=self._index.copy(),
270
+ name=self.name,
271
+ dtype=self.dtype
272
+ )
273
+
274
+ def map(self, mapping: Union[Dict[Any, Any], Callable[[Any], Any]]) -> 'CreatesonlineSeries':
275
+ """Map values using dictionary or function"""
276
+ if callable(mapping):
277
+ return self.apply(mapping)
278
+ else:
279
+ new_data = [mapping.get(val, val) for val in self._data]
280
+ return CreatesonlineSeries(
281
+ data=new_data,
282
+ index=self._index.copy(),
283
+ name=self.name,
284
+ dtype=self.dtype
285
+ )
286
+
287
+ def filter(self, condition: Callable[[Any], bool]) -> 'CreatesonlineSeries':
288
+ """Filter series based on condition"""
289
+ filtered_data = []
290
+ filtered_index = []
291
+
292
+ for val, idx in zip(self._data, self._index):
293
+ if condition(val):
294
+ filtered_data.append(val)
295
+ filtered_index.append(idx)
296
+
297
+ return CreatesonlineSeries(
298
+ data=filtered_data,
299
+ index=filtered_index,
300
+ name=self.name,
301
+ dtype=self.dtype
302
+ )
303
+
304
+ def dropna(self) -> 'CreatesonlineSeries':
305
+ """Drop null/None values"""
306
+ return self.filter(lambda x: x is not None)
307
+
308
+ def fillna(self, value: Any) -> 'CreatesonlineSeries':
309
+ """Fill null/None values with specified value"""
310
+ return self.map(lambda x: value if x is None else x)
311
+
312
+ def isna(self) -> 'CreatesonlineSeries':
313
+ """Check for null/None values"""
314
+ return CreatesonlineSeries(
315
+ data=[val is None for val in self._data],
316
+ index=self._index.copy(),
317
+ name=f'{self.name}_isna' if self.name else 'isna'
318
+ )
319
+
320
+ def sum(self) -> Union[float, int]:
321
+ """Sum of numeric values"""
322
+ numeric_values = [val for val in self._data if isinstance(val, (int, float))]
323
+ return sum(numeric_values) if numeric_values else 0
324
+
325
+ def mean(self) -> float:
326
+ """Mean of numeric values"""
327
+ numeric_values = [val for val in self._data if isinstance(val, (int, float))]
328
+ return sum(numeric_values) / len(numeric_values) if numeric_values else 0.0
329
+
330
+ def median(self) -> float:
331
+ """Median of numeric values"""
332
+ numeric_values = sorted([val for val in self._data if isinstance(val, (int, float))])
333
+ n = len(numeric_values)
334
+ if n == 0:
335
+ return 0.0
336
+ elif n % 2 == 0:
337
+ return (numeric_values[n//2 - 1] + numeric_values[n//2]) / 2
338
+ else:
339
+ return numeric_values[n//2]
340
+
341
+ def std(self) -> float:
342
+ """Standard deviation of numeric values"""
343
+ numeric_values = [val for val in self._data if isinstance(val, (int, float))]
344
+ if len(numeric_values) < 2:
345
+ return 0.0
346
+
347
+ mean_val = self.mean()
348
+ variance = sum((val - mean_val) ** 2 for val in numeric_values) / (len(numeric_values) - 1)
349
+ return variance ** 0.5
350
+
351
+ def min(self) -> Any:
352
+ """Minimum value"""
353
+ return min(self._data) if self._data else None
354
+
355
+ def max(self) -> Any:
356
+ """Maximum value"""
357
+ return max(self._data) if self._data else None
358
+
359
+ def describe(self) -> Dict[str, Any]:
360
+ """Descriptive statistics"""
361
+ numeric_values = [val for val in self._data if isinstance(val, (int, float))]
362
+
363
+ if not numeric_values:
364
+ return {
365
+ 'count': len(self._data),
366
+ 'unique': len(set(self._data)),
367
+ 'top': max(set(self._data), key=self._data.count) if self._data else None,
368
+ 'freq': max([self._data.count(val) for val in set(self._data)]) if self._data else 0
369
+ }
370
+
371
+ return {
372
+ 'count': len(numeric_values),
373
+ 'mean': self.mean(),
374
+ 'std': self.std(),
375
+ 'min': min(numeric_values),
376
+ '25%': self._quantile(numeric_values, 0.25),
377
+ '50%': self.median(),
378
+ '75%': self._quantile(numeric_values, 0.75),
379
+ 'max': max(numeric_values)
380
+ }
381
+
382
+ def _quantile(self, values: List[Union[int, float]], q: float) -> float:
383
+ """Calculate quantile"""
384
+ sorted_values = sorted(values)
385
+ n = len(sorted_values)
386
+ index = q * (n - 1)
387
+
388
+ if index.is_integer():
389
+ return sorted_values[int(index)]
390
+ else:
391
+ lower = sorted_values[int(index)]
392
+ upper = sorted_values[int(index) + 1]
393
+ return lower + (upper - lower) * (index - int(index))
394
+
395
+ def to_dict(self) -> Dict[str, Any]:
396
+ """Convert series to dictionary"""
397
+ return dict(zip(self._index, self._data))
398
+
399
+ def to_list(self) -> List[Any]:
400
+ """Convert series to list"""
401
+ return self._data.copy()
402
+
403
+ def to_json(self, indent: Optional[int] = None) -> str:
404
+ """Convert series to JSON string"""
405
+ return json.dumps(self.to_dict(), indent=indent, default=str)
406
+
407
+ def to_numpy(self) -> NDArrayType:
408
+ """Convert series to numpy array"""
409
+ return np.array(self._data)
410
+
411
+ # Mathematical operations
412
+ def __add__(self, other: Union['CreatesonlineSeries', int, float]) -> 'CreatesonlineSeries':
413
+ """Addition"""
414
+ if isinstance(other, CreatesonlineSeries):
415
+ if len(self) != len(other):
416
+ raise ValueError("Series lengths must match")
417
+ new_data = [a + b for a, b in zip(self._data, other._data)]
418
+ else:
419
+ new_data = [val + other if isinstance(val, (int, float)) else val for val in self._data]
420
+
421
+ return CreatesonlineSeries(
422
+ data=new_data,
423
+ index=self._index.copy(),
424
+ name=self.name
425
+ )
426
+
427
+ def __sub__(self, other: Union['CreatesonlineSeries', int, float]) -> 'CreatesonlineSeries':
428
+ """Subtraction"""
429
+ if isinstance(other, CreatesonlineSeries):
430
+ if len(self) != len(other):
431
+ raise ValueError("Series lengths must match")
432
+ new_data = [a - b for a, b in zip(self._data, other._data)]
433
+ else:
434
+ new_data = [val - other if isinstance(val, (int, float)) else val for val in self._data]
435
+
436
+ return CreatesonlineSeries(
437
+ data=new_data,
438
+ index=self._index.copy(),
439
+ name=self.name
440
+ )
441
+
442
+ def __mul__(self, other: Union['CreatesonlineSeries', int, float]) -> 'CreatesonlineSeries':
443
+ """Multiplication"""
444
+ if isinstance(other, CreatesonlineSeries):
445
+ if len(self) != len(other):
446
+ raise ValueError("Series lengths must match")
447
+ new_data = [a * b for a, b in zip(self._data, other._data)]
448
+ else:
449
+ new_data = [val * other if isinstance(val, (int, float)) else val for val in self._data]
450
+
451
+ return CreatesonlineSeries(
452
+ data=new_data,
453
+ index=self._index.copy(),
454
+ name=self.name
455
+ )
456
+
457
+ def __truediv__(self, other: Union['CreatesonlineSeries', int, float]) -> 'CreatesonlineSeries':
458
+ """Division"""
459
+ if isinstance(other, CreatesonlineSeries):
460
+ if len(self) != len(other):
461
+ raise ValueError("Series lengths must match")
462
+ new_data = [a / b if b != 0 else float('inf') for a, b in zip(self._data, other._data)]
463
+ else:
464
+ if other == 0:
465
+ raise ZeroDivisionError("Division by zero")
466
+ new_data = [val / other if isinstance(val, (int, float)) else val for val in self._data]
467
+
468
+ return CreatesonlineSeries(
469
+ data=new_data,
470
+ index=self._index.copy(),
471
+ name=self.name
472
+ )
473
+
474
+ # Comparison operations
475
+ def __eq__(self, other: Union['CreatesonlineSeries', Any]) -> 'CreatesonlineSeries':
476
+ """Equality comparison"""
477
+ if isinstance(other, CreatesonlineSeries):
478
+ new_data = [a == b for a, b in zip(self._data, other._data)]
479
+ else:
480
+ new_data = [val == other for val in self._data]
481
+
482
+ return CreatesonlineSeries(
483
+ data=new_data,
484
+ index=self._index.copy(),
485
+ name=f'{self.name}_eq' if self.name else 'eq'
486
+ )
487
+
488
+ def __ne__(self, other: Union['CreatesonlineSeries', Any]) -> 'CreatesonlineSeries':
489
+ """Not equal comparison"""
490
+ return ~(self == other)
491
+
492
+ def __lt__(self, other: Union['CreatesonlineSeries', Any]) -> 'CreatesonlineSeries':
493
+ """Less than comparison"""
494
+ if isinstance(other, CreatesonlineSeries):
495
+ new_data = [a < b for a, b in zip(self._data, other._data)]
496
+ else:
497
+ new_data = [val < other if isinstance(val, (int, float)) else False for val in self._data]
498
+
499
+ return CreatesonlineSeries(
500
+ data=new_data,
501
+ index=self._index.copy(),
502
+ name=f'{self.name}_lt' if self.name else 'lt'
503
+ )
504
+
505
+ def __le__(self, other: Union['CreatesonlineSeries', Any]) -> 'CreatesonlineSeries':
506
+ """Less than or equal comparison"""
507
+ return (self < other) | (self == other)
508
+
509
+ def __gt__(self, other: Union['CreatesonlineSeries', Any]) -> 'CreatesonlineSeries':
510
+ """Greater than comparison"""
511
+ if isinstance(other, CreatesonlineSeries):
512
+ new_data = [a > b for a, b in zip(self._data, other._data)]
513
+ else:
514
+ new_data = [val > other if isinstance(val, (int, float)) else False for val in self._data]
515
+
516
+ return CreatesonlineSeries(
517
+ data=new_data,
518
+ index=self._index.copy(),
519
+ name=f'{self.name}_gt' if self.name else 'gt'
520
+ )
521
+
522
+ def __ge__(self, other: Union['CreatesonlineSeries', Any]) -> 'CreatesonlineSeries':
523
+ """Greater than or equal comparison"""
524
+ return (self > other) | (self == other)
525
+
526
+ def __invert__(self) -> 'CreatesonlineSeries':
527
+ """Logical NOT for boolean series"""
528
+ new_data = [not val for val in self._data]
529
+ return CreatesonlineSeries(
530
+ data=new_data,
531
+ index=self._index.copy(),
532
+ name=f'{self.name}_not' if self.name else 'not'
533
+ )
534
+
535
+ def __or__(self, other: 'CreatesonlineSeries') -> 'CreatesonlineSeries':
536
+ """Logical OR for boolean series"""
537
+ if len(self) != len(other):
538
+ raise ValueError("Series lengths must match")
539
+
540
+ new_data = [a or b for a, b in zip(self._data, other._data)]
541
+ return CreatesonlineSeries(
542
+ data=new_data,
543
+ index=self._index.copy(),
544
+ name=f'{self.name}_or' if self.name else 'or'
545
+ )
546
+
547
+ def __and__(self, other: 'CreatesonlineSeries') -> 'CreatesonlineSeries':
548
+ """Logical AND for boolean series"""
549
+ if len(self) != len(other):
550
+ raise ValueError("Series lengths must match")
551
+
552
+ new_data = [a and b for a, b in zip(self._data, other._data)]
553
+ return CreatesonlineSeries(
554
+ data=new_data,
555
+ index=self._index.copy(),
556
+ name=f'{self.name}_and' if self.name else 'and'
557
+ )
@@ -0,0 +1,60 @@
1
+ """
2
+ CREATESONLINE Database Abstraction Layer
3
+
4
+ Pure Python database abstraction with zero external dependencies (except SQLAlchemy).
5
+ Clean API that hides SQLAlchemy complexity while providing AI-native features.
6
+ """
7
+
8
+ from .abstraction import Database, Connection, Transaction
9
+ from .models import CreatesonlineModel, QueryBuilder
10
+ from .fields import (
11
+ CreatesonlineField, StringField, IntegerField, FloatField,
12
+ BooleanField, DateTimeField, TextField, JSONField,
13
+ EmbeddingField, SlugField, EmailField, URLField
14
+ )
15
+ from .migrations import MigrationManager, Migration
16
+
17
+ __all__ = [
18
+ # Core database
19
+ 'Database',
20
+ 'Connection',
21
+ 'Transaction',
22
+
23
+ # Models
24
+ 'CreatesonlineModel',
25
+ 'QueryBuilder',
26
+
27
+ # Fields
28
+ 'CreatesonlineField',
29
+ 'StringField',
30
+ 'IntegerField',
31
+ 'FloatField',
32
+ 'BooleanField',
33
+ 'DateTimeField',
34
+ 'TextField',
35
+ 'JSONField',
36
+ 'EmbeddingField',
37
+ 'SlugField',
38
+ 'EmailField',
39
+ 'URLField',
40
+
41
+ # Migrations
42
+ 'MigrationManager',
43
+ 'Migration'
44
+ ]
45
+
46
+ # Global database instance
47
+ _database_instance = None
48
+
49
+ def get_database() -> Database:
50
+ """Get global database instance"""
51
+ global _database_instance
52
+ if _database_instance is None:
53
+ _database_instance = Database()
54
+ return _database_instance
55
+
56
+ def init_database(database_url: str = None, **kwargs) -> Database:
57
+ """Initialize database with custom configuration"""
58
+ global _database_instance
59
+ _database_instance = Database(database_url=database_url, **kwargs)
60
+ return _database_instance