masonite-framework-orm 3.0.1__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.
- masonite_framework_orm-3.0.1.dist-info/METADATA +87 -0
- masonite_framework_orm-3.0.1.dist-info/RECORD +116 -0
- masonite_framework_orm-3.0.1.dist-info/WHEEL +5 -0
- masonite_framework_orm-3.0.1.dist-info/entry_points.txt +3 -0
- masonite_framework_orm-3.0.1.dist-info/licenses/LICENSE +21 -0
- masonite_framework_orm-3.0.1.dist-info/top_level.txt +1 -0
- masoniteorm/__init__.py +1 -0
- masoniteorm/collection/Collection.py +605 -0
- masoniteorm/collection/__init__.py +1 -0
- masoniteorm/commands/CanOverrideConfig.py +16 -0
- masoniteorm/commands/CanOverrideOptionsDefault.py +22 -0
- masoniteorm/commands/Command.py +6 -0
- masoniteorm/commands/Entry.py +43 -0
- masoniteorm/commands/MakeMigrationCommand.py +57 -0
- masoniteorm/commands/MakeModelCommand.py +78 -0
- masoniteorm/commands/MakeModelDocstringCommand.py +37 -0
- masoniteorm/commands/MakeObserverCommand.py +54 -0
- masoniteorm/commands/MakeSeedCommand.py +54 -0
- masoniteorm/commands/MigrateCommand.py +46 -0
- masoniteorm/commands/MigrateFreshCommand.py +41 -0
- masoniteorm/commands/MigrateRefreshCommand.py +41 -0
- masoniteorm/commands/MigrateResetCommand.py +25 -0
- masoniteorm/commands/MigrateRollbackCommand.py +26 -0
- masoniteorm/commands/MigrateStatusCommand.py +51 -0
- masoniteorm/commands/SeedRunCommand.py +35 -0
- masoniteorm/commands/ShellCommand.py +205 -0
- masoniteorm/commands/__init__.py +18 -0
- masoniteorm/commands/stubs/create_migration.stub +20 -0
- masoniteorm/commands/stubs/create_seed.stub +9 -0
- masoniteorm/commands/stubs/model.stub +9 -0
- masoniteorm/commands/stubs/observer.stub +101 -0
- masoniteorm/commands/stubs/table_migration.stub +19 -0
- masoniteorm/config.py +123 -0
- masoniteorm/connections/BaseConnection.py +101 -0
- masoniteorm/connections/ConnectionFactory.py +59 -0
- masoniteorm/connections/ConnectionResolver.py +132 -0
- masoniteorm/connections/MSSQLConnection.py +176 -0
- masoniteorm/connections/MySQLConnection.py +232 -0
- masoniteorm/connections/PostgresConnection.py +225 -0
- masoniteorm/connections/SQLiteConnection.py +179 -0
- masoniteorm/connections/__init__.py +6 -0
- masoniteorm/exceptions.py +38 -0
- masoniteorm/expressions/__init__.py +1 -0
- masoniteorm/expressions/expressions.py +288 -0
- masoniteorm/factories/Factory.py +112 -0
- masoniteorm/factories/__init__.py +1 -0
- masoniteorm/helpers/__init__.py +0 -0
- masoniteorm/helpers/misc.py +22 -0
- masoniteorm/migrations/Migration.py +330 -0
- masoniteorm/migrations/__init__.py +1 -0
- masoniteorm/models/MigrationModel.py +9 -0
- masoniteorm/models/Model.py +1209 -0
- masoniteorm/models/Model.pyi +1366 -0
- masoniteorm/models/Pivot.py +5 -0
- masoniteorm/models/__init__.py +1 -0
- masoniteorm/observers/ObservesEvents.py +27 -0
- masoniteorm/observers/__init__.py +1 -0
- masoniteorm/pagination/BasePaginator.py +10 -0
- masoniteorm/pagination/LengthAwarePaginator.py +34 -0
- masoniteorm/pagination/SimplePaginator.py +28 -0
- masoniteorm/pagination/__init__.py +2 -0
- masoniteorm/providers/ORMProvider.py +39 -0
- masoniteorm/providers/__init__.py +1 -0
- masoniteorm/query/EagerRelation.py +42 -0
- masoniteorm/query/QueryBuilder.py +2486 -0
- masoniteorm/query/__init__.py +1 -0
- masoniteorm/query/grammars/BaseGrammar.py +1027 -0
- masoniteorm/query/grammars/MSSQLGrammar.py +194 -0
- masoniteorm/query/grammars/MySQLGrammar.py +238 -0
- masoniteorm/query/grammars/PostgresGrammar.py +213 -0
- masoniteorm/query/grammars/SQLiteGrammar.py +228 -0
- masoniteorm/query/grammars/__init__.py +4 -0
- masoniteorm/query/processors/MSSQLPostProcessor.py +58 -0
- masoniteorm/query/processors/MySQLPostProcessor.py +48 -0
- masoniteorm/query/processors/PostgresPostProcessor.py +49 -0
- masoniteorm/query/processors/SQLitePostProcessor.py +49 -0
- masoniteorm/query/processors/__init__.py +4 -0
- masoniteorm/relationships/BaseRelationship.py +161 -0
- masoniteorm/relationships/BelongsTo.py +124 -0
- masoniteorm/relationships/BelongsToMany.py +604 -0
- masoniteorm/relationships/HasMany.py +66 -0
- masoniteorm/relationships/HasManyThrough.py +269 -0
- masoniteorm/relationships/HasOne.py +111 -0
- masoniteorm/relationships/HasOneThrough.py +275 -0
- masoniteorm/relationships/MorphMany.py +152 -0
- masoniteorm/relationships/MorphOne.py +156 -0
- masoniteorm/relationships/MorphTo.py +111 -0
- masoniteorm/relationships/MorphToMany.py +108 -0
- masoniteorm/relationships/__init__.py +10 -0
- masoniteorm/schema/Blueprint.py +1161 -0
- masoniteorm/schema/Column.py +144 -0
- masoniteorm/schema/ColumnDiff.py +0 -0
- masoniteorm/schema/Constraint.py +5 -0
- masoniteorm/schema/ForeignKeyConstraint.py +28 -0
- masoniteorm/schema/Index.py +5 -0
- masoniteorm/schema/Schema.py +359 -0
- masoniteorm/schema/Table.py +94 -0
- masoniteorm/schema/TableDiff.py +86 -0
- masoniteorm/schema/__init__.py +3 -0
- masoniteorm/schema/platforms/MSSQLPlatform.py +367 -0
- masoniteorm/schema/platforms/MySQLPlatform.py +513 -0
- masoniteorm/schema/platforms/Platform.py +97 -0
- masoniteorm/schema/platforms/PostgresPlatform.py +551 -0
- masoniteorm/schema/platforms/SQLitePlatform.py +481 -0
- masoniteorm/schema/platforms/__init__.py +4 -0
- masoniteorm/scopes/BaseScope.py +6 -0
- masoniteorm/scopes/SoftDeleteScope.py +56 -0
- masoniteorm/scopes/SoftDeletesMixin.py +13 -0
- masoniteorm/scopes/TimeStampsMixin.py +12 -0
- masoniteorm/scopes/TimeStampsScope.py +47 -0
- masoniteorm/scopes/UUIDPrimaryKeyMixin.py +8 -0
- masoniteorm/scopes/UUIDPrimaryKeyScope.py +51 -0
- masoniteorm/scopes/__init__.py +8 -0
- masoniteorm/scopes/scope.py +15 -0
- masoniteorm/seeds/Seeder.py +42 -0
- masoniteorm/seeds/__init__.py +1 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import operator
|
|
3
|
+
import random
|
|
4
|
+
from functools import reduce
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Collection:
|
|
8
|
+
"""Wraps various data types to make working with them easier."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, items=None):
|
|
11
|
+
self._items = items or []
|
|
12
|
+
self.__appends__ = []
|
|
13
|
+
|
|
14
|
+
def take(self, number: int):
|
|
15
|
+
"""Takes a specific number of results from the items.
|
|
16
|
+
|
|
17
|
+
Arguments:
|
|
18
|
+
number {integer} -- The number of results to take.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
int
|
|
22
|
+
"""
|
|
23
|
+
if number < 0:
|
|
24
|
+
return self[number:]
|
|
25
|
+
|
|
26
|
+
return self[:number]
|
|
27
|
+
|
|
28
|
+
def first(self, callback=None):
|
|
29
|
+
"""Takes the first result in the items.
|
|
30
|
+
|
|
31
|
+
If a callback is given then the first result will be the result after the filter.
|
|
32
|
+
|
|
33
|
+
Keyword Arguments:
|
|
34
|
+
callback {callable} -- Used to filter the results before returning the first item. (default: {None})
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
mixed -- Returns whatever the first item is.
|
|
38
|
+
"""
|
|
39
|
+
filtered = self
|
|
40
|
+
if callback:
|
|
41
|
+
filtered = self.filter(callback)
|
|
42
|
+
response = None
|
|
43
|
+
|
|
44
|
+
if filtered:
|
|
45
|
+
response = filtered[0]
|
|
46
|
+
return response
|
|
47
|
+
|
|
48
|
+
def items(self):
|
|
49
|
+
return self._items.items()
|
|
50
|
+
|
|
51
|
+
def last(self, callback=None):
|
|
52
|
+
"""Takes the last result in the items.
|
|
53
|
+
|
|
54
|
+
If a callback is given then the last result will be the result after the filter.
|
|
55
|
+
|
|
56
|
+
Keyword Arguments:
|
|
57
|
+
callback {callable} -- Used to filter the results before returning the last item. (default: {None})
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
mixed -- Returns whatever the last item is.
|
|
61
|
+
"""
|
|
62
|
+
filtered = self
|
|
63
|
+
if callback:
|
|
64
|
+
filtered = self.filter(callback)
|
|
65
|
+
return filtered[-1]
|
|
66
|
+
|
|
67
|
+
def all(self):
|
|
68
|
+
"""Returns all the items.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
mixed -- Returns all items.
|
|
72
|
+
"""
|
|
73
|
+
return self._items
|
|
74
|
+
|
|
75
|
+
def avg(self, key=None):
|
|
76
|
+
"""Returns the average of the items.
|
|
77
|
+
|
|
78
|
+
If a key is given it will return the average of all the values of the key.
|
|
79
|
+
|
|
80
|
+
Keyword Arguments:
|
|
81
|
+
key {string} -- The key to use to find the average of all the values of that key. (default: {None})
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
int -- Returns the average.
|
|
85
|
+
"""
|
|
86
|
+
result = 0
|
|
87
|
+
items = self._get_value(key) or self._items
|
|
88
|
+
try:
|
|
89
|
+
result = sum(items) / len(items)
|
|
90
|
+
except TypeError:
|
|
91
|
+
pass
|
|
92
|
+
return result
|
|
93
|
+
|
|
94
|
+
def max(self, key=None):
|
|
95
|
+
"""Returns the max of the items.
|
|
96
|
+
|
|
97
|
+
If a key is given it will return the max of all the values of the key.
|
|
98
|
+
|
|
99
|
+
Keyword Arguments:
|
|
100
|
+
key {string} -- The key to use to find the max of all the values of that key. (default: {None})
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
int -- Returns the max.
|
|
104
|
+
"""
|
|
105
|
+
result = 0
|
|
106
|
+
items = self._get_value(key) or self._items
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
return max(items)
|
|
110
|
+
except (TypeError, ValueError):
|
|
111
|
+
pass
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
def min(self, key=None):
|
|
115
|
+
"""Returns the min of the items.
|
|
116
|
+
|
|
117
|
+
If a key is given it will return the min of all the values of the key.
|
|
118
|
+
|
|
119
|
+
Keyword Arguments:
|
|
120
|
+
key {string} -- The key to use to find the min of all the values of that key. (default: {None})
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
int -- Returns the min.
|
|
124
|
+
"""
|
|
125
|
+
result = 0
|
|
126
|
+
items = self._get_value(key) or self._items
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
return min(items)
|
|
130
|
+
except (TypeError, ValueError):
|
|
131
|
+
pass
|
|
132
|
+
return result
|
|
133
|
+
|
|
134
|
+
def chunk(self, size: int):
|
|
135
|
+
"""Chunks the items.
|
|
136
|
+
|
|
137
|
+
Keyword Arguments:
|
|
138
|
+
size {integer} -- The number of values in each chunk.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
int -- Returns the average.
|
|
142
|
+
"""
|
|
143
|
+
items = []
|
|
144
|
+
for i in range(0, self.count(), size):
|
|
145
|
+
items.append(self[i : i + size])
|
|
146
|
+
return self.__class__(items)
|
|
147
|
+
|
|
148
|
+
def collapse(self):
|
|
149
|
+
items = []
|
|
150
|
+
for item in self:
|
|
151
|
+
items += self.__get_items(item)
|
|
152
|
+
return self.__class__(items)
|
|
153
|
+
|
|
154
|
+
def contains(self, key, value=None):
|
|
155
|
+
if value:
|
|
156
|
+
return self.contains(lambda x: self._data_get(x, key) == value)
|
|
157
|
+
|
|
158
|
+
if self._check_is_callable(key, raise_exception=False):
|
|
159
|
+
return self.first(key) is not None
|
|
160
|
+
|
|
161
|
+
return key in self
|
|
162
|
+
|
|
163
|
+
def count(self):
|
|
164
|
+
return len(self._items)
|
|
165
|
+
|
|
166
|
+
def diff(self, items):
|
|
167
|
+
items = self.__get_items(items)
|
|
168
|
+
return self.__class__([x for x in self if x not in items])
|
|
169
|
+
|
|
170
|
+
def each(self, callback):
|
|
171
|
+
self._check_is_callable(callback)
|
|
172
|
+
|
|
173
|
+
for k, v in enumerate(self):
|
|
174
|
+
result = callback(v)
|
|
175
|
+
if not result:
|
|
176
|
+
break
|
|
177
|
+
self[k] = result
|
|
178
|
+
|
|
179
|
+
def every(self, callback):
|
|
180
|
+
self._check_is_callable(callback)
|
|
181
|
+
return all([callback(x) for x in self])
|
|
182
|
+
|
|
183
|
+
def filter(self, callback):
|
|
184
|
+
self._check_is_callable(callback)
|
|
185
|
+
return self.__class__(list(filter(callback, self)))
|
|
186
|
+
|
|
187
|
+
def flatten(self):
|
|
188
|
+
def _flatten(items):
|
|
189
|
+
if isinstance(items, dict):
|
|
190
|
+
for v in items.values():
|
|
191
|
+
for x in _flatten(v):
|
|
192
|
+
yield x
|
|
193
|
+
elif isinstance(items, list):
|
|
194
|
+
for i in items:
|
|
195
|
+
for j in _flatten(i):
|
|
196
|
+
yield j
|
|
197
|
+
else:
|
|
198
|
+
yield items
|
|
199
|
+
|
|
200
|
+
return self.__class__(list(_flatten(self._items)))
|
|
201
|
+
|
|
202
|
+
def forget(self, *keys):
|
|
203
|
+
keys = reversed(sorted(keys))
|
|
204
|
+
|
|
205
|
+
for key in keys:
|
|
206
|
+
del self[key]
|
|
207
|
+
|
|
208
|
+
return self
|
|
209
|
+
|
|
210
|
+
def for_page(self, page, number):
|
|
211
|
+
return self.__class__(self[page:number])
|
|
212
|
+
|
|
213
|
+
def get(self, key, default=None):
|
|
214
|
+
try:
|
|
215
|
+
return self[key]
|
|
216
|
+
except IndexError:
|
|
217
|
+
pass
|
|
218
|
+
|
|
219
|
+
return self._value(default)
|
|
220
|
+
|
|
221
|
+
def implode(self, glue=",", key=None):
|
|
222
|
+
first = self.first()
|
|
223
|
+
if not isinstance(first, str) and key:
|
|
224
|
+
return glue.join(self.pluck(key))
|
|
225
|
+
return glue.join([str(x) for x in self])
|
|
226
|
+
|
|
227
|
+
def is_empty(self):
|
|
228
|
+
return not self
|
|
229
|
+
|
|
230
|
+
def map(self, callback):
|
|
231
|
+
self._check_is_callable(callback)
|
|
232
|
+
items = [callback(x) for x in self]
|
|
233
|
+
return self.__class__(items)
|
|
234
|
+
|
|
235
|
+
def map_into(self, cls, method=None, **kwargs):
|
|
236
|
+
results = []
|
|
237
|
+
for item in self:
|
|
238
|
+
if method:
|
|
239
|
+
results.append(getattr(cls, method)(item, **kwargs))
|
|
240
|
+
else:
|
|
241
|
+
results.append(cls(item))
|
|
242
|
+
|
|
243
|
+
return self.__class__(results)
|
|
244
|
+
|
|
245
|
+
def merge(self, items):
|
|
246
|
+
if isinstance(items, Collection):
|
|
247
|
+
items = items._items
|
|
248
|
+
elif not isinstance(items, list):
|
|
249
|
+
raise ValueError("Unable to merge uncompatible types")
|
|
250
|
+
|
|
251
|
+
items = self.__get_items(items)
|
|
252
|
+
|
|
253
|
+
self._items += items
|
|
254
|
+
return self
|
|
255
|
+
|
|
256
|
+
def pluck(self, value, key=None, keep_nulls=True):
|
|
257
|
+
if key:
|
|
258
|
+
attributes = {}
|
|
259
|
+
else:
|
|
260
|
+
attributes = []
|
|
261
|
+
|
|
262
|
+
if isinstance(self._items, dict):
|
|
263
|
+
return Collection([self._items.get(value)])
|
|
264
|
+
|
|
265
|
+
for item in self:
|
|
266
|
+
if isinstance(item, dict):
|
|
267
|
+
iterable = item.items()
|
|
268
|
+
elif hasattr(item, "serialize"):
|
|
269
|
+
iterable = item.serialize().items()
|
|
270
|
+
else:
|
|
271
|
+
iterable = self.all().items()
|
|
272
|
+
|
|
273
|
+
for k, v in iterable:
|
|
274
|
+
if keep_nulls is False and v is None:
|
|
275
|
+
continue
|
|
276
|
+
|
|
277
|
+
if k == value:
|
|
278
|
+
if key:
|
|
279
|
+
attributes[self._data_get(item, key)] = self._data_get(
|
|
280
|
+
item, value
|
|
281
|
+
)
|
|
282
|
+
else:
|
|
283
|
+
attributes.append(v)
|
|
284
|
+
|
|
285
|
+
return Collection(attributes)
|
|
286
|
+
|
|
287
|
+
def pop(self):
|
|
288
|
+
last = self._items.pop()
|
|
289
|
+
return last
|
|
290
|
+
|
|
291
|
+
def prepend(self, value):
|
|
292
|
+
self._items.insert(0, value)
|
|
293
|
+
return self
|
|
294
|
+
|
|
295
|
+
def pull(self, key):
|
|
296
|
+
value = self.get(key)
|
|
297
|
+
self.forget(key)
|
|
298
|
+
return value
|
|
299
|
+
|
|
300
|
+
def push(self, value):
|
|
301
|
+
self._items.append(value)
|
|
302
|
+
|
|
303
|
+
def put(self, key, value):
|
|
304
|
+
self._items[key] = value
|
|
305
|
+
return self
|
|
306
|
+
|
|
307
|
+
def random(self, count=None):
|
|
308
|
+
"""Returns a random item of the collection."""
|
|
309
|
+
collection_count = self.count()
|
|
310
|
+
if collection_count == 0:
|
|
311
|
+
return None
|
|
312
|
+
elif count and count > collection_count:
|
|
313
|
+
raise ValueError(
|
|
314
|
+
"count argument must be inferior to collection length."
|
|
315
|
+
)
|
|
316
|
+
elif count:
|
|
317
|
+
self._items = random.sample(self._items, k=count)
|
|
318
|
+
return self
|
|
319
|
+
else:
|
|
320
|
+
return random.choice(self._items)
|
|
321
|
+
|
|
322
|
+
def reduce(self, callback, initial=0):
|
|
323
|
+
return reduce(callback, self, initial)
|
|
324
|
+
|
|
325
|
+
def reject(self, callback):
|
|
326
|
+
self._check_is_callable(callback)
|
|
327
|
+
|
|
328
|
+
items = self._get_value(callback) or self._items
|
|
329
|
+
self._items = items
|
|
330
|
+
|
|
331
|
+
def reverse(self):
|
|
332
|
+
self._items = self[::-1]
|
|
333
|
+
|
|
334
|
+
def serialize(self, *args, **kwargs):
|
|
335
|
+
def _serialize(item):
|
|
336
|
+
if self.__appends__:
|
|
337
|
+
item.set_appends(self.__appends__)
|
|
338
|
+
|
|
339
|
+
if hasattr(item, "serialize"):
|
|
340
|
+
return item.serialize(*args, **kwargs)
|
|
341
|
+
elif hasattr(item, "to_dict"):
|
|
342
|
+
return item.to_dict()
|
|
343
|
+
return item
|
|
344
|
+
|
|
345
|
+
return list(map(_serialize, self))
|
|
346
|
+
|
|
347
|
+
def add_relation(self, result=None):
|
|
348
|
+
for model in self._items:
|
|
349
|
+
model.add_relation(result or {})
|
|
350
|
+
|
|
351
|
+
return self
|
|
352
|
+
|
|
353
|
+
def shift(self):
|
|
354
|
+
return self.pull(0)
|
|
355
|
+
|
|
356
|
+
def sort(self, key=None):
|
|
357
|
+
if key:
|
|
358
|
+
self._items.sort(key=lambda x: x[key], reverse=False)
|
|
359
|
+
return self
|
|
360
|
+
|
|
361
|
+
self._items = sorted(self)
|
|
362
|
+
return self
|
|
363
|
+
|
|
364
|
+
def sum(self, key=None):
|
|
365
|
+
result = 0
|
|
366
|
+
items = self._get_value(key) or self._items
|
|
367
|
+
try:
|
|
368
|
+
result = sum(items)
|
|
369
|
+
except TypeError:
|
|
370
|
+
pass
|
|
371
|
+
return result
|
|
372
|
+
|
|
373
|
+
def to_json(self, **kwargs):
|
|
374
|
+
return json.dumps(self.serialize(), **kwargs)
|
|
375
|
+
|
|
376
|
+
def group_by(self, key):
|
|
377
|
+
from itertools import groupby
|
|
378
|
+
|
|
379
|
+
self.sort(key)
|
|
380
|
+
|
|
381
|
+
new_dict = {}
|
|
382
|
+
|
|
383
|
+
for k, v in groupby(self._items, key=lambda x: x[key]):
|
|
384
|
+
new_dict.update({k: list(v)})
|
|
385
|
+
|
|
386
|
+
return Collection(new_dict)
|
|
387
|
+
|
|
388
|
+
def transform(self, callback):
|
|
389
|
+
self._check_is_callable(callback)
|
|
390
|
+
self._items = self._get_value(callback)
|
|
391
|
+
|
|
392
|
+
def unique(self, key=None):
|
|
393
|
+
if not key:
|
|
394
|
+
items = list(set(self._items))
|
|
395
|
+
return self.__class__(items)
|
|
396
|
+
|
|
397
|
+
keys = set()
|
|
398
|
+
items = []
|
|
399
|
+
if isinstance(self.all(), dict):
|
|
400
|
+
return self
|
|
401
|
+
|
|
402
|
+
for item in self:
|
|
403
|
+
if isinstance(item, dict):
|
|
404
|
+
comparison = item.get(key)
|
|
405
|
+
elif isinstance(item, str):
|
|
406
|
+
comparison = item
|
|
407
|
+
else:
|
|
408
|
+
comparison = getattr(item, key)
|
|
409
|
+
if comparison not in keys:
|
|
410
|
+
items.append(item)
|
|
411
|
+
keys.add(comparison)
|
|
412
|
+
|
|
413
|
+
return self.__class__(items)
|
|
414
|
+
|
|
415
|
+
def where(self, key, *args):
|
|
416
|
+
op = "=="
|
|
417
|
+
value = args[0]
|
|
418
|
+
|
|
419
|
+
if len(args) >= 2:
|
|
420
|
+
op = args[0]
|
|
421
|
+
value = args[1]
|
|
422
|
+
|
|
423
|
+
attributes = []
|
|
424
|
+
|
|
425
|
+
for item in self._items:
|
|
426
|
+
if isinstance(item, dict):
|
|
427
|
+
comparison = item.get(key)
|
|
428
|
+
else:
|
|
429
|
+
comparison = (
|
|
430
|
+
getattr(item, key) if hasattr(item, key) else False
|
|
431
|
+
)
|
|
432
|
+
if self._make_comparison(comparison, value, op):
|
|
433
|
+
attributes.append(item)
|
|
434
|
+
return self.__class__(attributes)
|
|
435
|
+
|
|
436
|
+
def where_in(self, key, args: list) -> "Collection":
|
|
437
|
+
# Compatibility patch - allow numeric strings to match integers
|
|
438
|
+
# (if all args are numeric strings)
|
|
439
|
+
if all([isinstance(arg, str) and arg.isnumeric() for arg in args]):
|
|
440
|
+
return self.where_in(key, [int(arg) for arg in args])
|
|
441
|
+
|
|
442
|
+
attributes = []
|
|
443
|
+
|
|
444
|
+
for item in self._items:
|
|
445
|
+
if isinstance(item, dict):
|
|
446
|
+
if key not in item:
|
|
447
|
+
continue
|
|
448
|
+
comparison = item.get(key)
|
|
449
|
+
else:
|
|
450
|
+
if not hasattr(item, key):
|
|
451
|
+
continue
|
|
452
|
+
comparison = getattr(item, key)
|
|
453
|
+
|
|
454
|
+
if comparison in args:
|
|
455
|
+
attributes.append(item)
|
|
456
|
+
|
|
457
|
+
return self.__class__(attributes)
|
|
458
|
+
|
|
459
|
+
def where_not_in(self, key, args: list) -> "Collection":
|
|
460
|
+
# Compatibility patch - allow numeric strings to match integers
|
|
461
|
+
# (if all args are numeric strings)
|
|
462
|
+
if all([isinstance(arg, str) and arg.isnumeric() for arg in args]):
|
|
463
|
+
return self.where_not_in(key, [int(arg) for arg in args])
|
|
464
|
+
|
|
465
|
+
attributes = []
|
|
466
|
+
|
|
467
|
+
for item in self._items:
|
|
468
|
+
if isinstance(item, dict):
|
|
469
|
+
if key not in item:
|
|
470
|
+
continue
|
|
471
|
+
comparison = item.get(key)
|
|
472
|
+
else:
|
|
473
|
+
if not hasattr(item, key):
|
|
474
|
+
continue
|
|
475
|
+
comparison = getattr(item, key)
|
|
476
|
+
|
|
477
|
+
if comparison not in args:
|
|
478
|
+
attributes.append(item)
|
|
479
|
+
|
|
480
|
+
return self.__class__(attributes)
|
|
481
|
+
|
|
482
|
+
def zip(self, items):
|
|
483
|
+
items = self.__get_items(items)
|
|
484
|
+
if not isinstance(items, list):
|
|
485
|
+
raise ValueError(
|
|
486
|
+
"The 'items' parameter must be a list or a Collection"
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
_items = []
|
|
490
|
+
for x, y in zip(self, items):
|
|
491
|
+
_items.append([x, y])
|
|
492
|
+
return self.__class__(_items)
|
|
493
|
+
|
|
494
|
+
def set_appends(self, appends):
|
|
495
|
+
"""
|
|
496
|
+
Set the attributes that should be appended to the Collection.
|
|
497
|
+
|
|
498
|
+
:rtype: list
|
|
499
|
+
"""
|
|
500
|
+
self.__appends__ += appends
|
|
501
|
+
return self
|
|
502
|
+
|
|
503
|
+
def _get_value(self, key):
|
|
504
|
+
if not key:
|
|
505
|
+
return None
|
|
506
|
+
|
|
507
|
+
items = []
|
|
508
|
+
for item in self:
|
|
509
|
+
if isinstance(key, str):
|
|
510
|
+
if hasattr(item, key) or (key in item):
|
|
511
|
+
items.append(getattr(item, key, item[key]))
|
|
512
|
+
elif callable(key):
|
|
513
|
+
result = key(item)
|
|
514
|
+
if result:
|
|
515
|
+
items.append(result)
|
|
516
|
+
return items
|
|
517
|
+
|
|
518
|
+
def _data_get(self, item, key, default=None):
|
|
519
|
+
try:
|
|
520
|
+
if isinstance(item, (list, tuple, dict)):
|
|
521
|
+
item = item[key]
|
|
522
|
+
elif isinstance(item, object):
|
|
523
|
+
item = getattr(item, key)
|
|
524
|
+
except (IndexError, AttributeError, KeyError, TypeError):
|
|
525
|
+
return self._value(default)
|
|
526
|
+
|
|
527
|
+
return item
|
|
528
|
+
|
|
529
|
+
def _value(self, value):
|
|
530
|
+
if callable(value):
|
|
531
|
+
return value()
|
|
532
|
+
return value
|
|
533
|
+
|
|
534
|
+
def _check_is_callable(self, callback, raise_exception=True):
|
|
535
|
+
if not callable(callback):
|
|
536
|
+
if not raise_exception:
|
|
537
|
+
return False
|
|
538
|
+
raise ValueError("The 'callback' should be a function")
|
|
539
|
+
return True
|
|
540
|
+
|
|
541
|
+
def _make_comparison(self, a, b, op):
|
|
542
|
+
operators = {
|
|
543
|
+
"<": operator.lt,
|
|
544
|
+
"<=": operator.le,
|
|
545
|
+
"==": operator.eq,
|
|
546
|
+
"!=": operator.ne,
|
|
547
|
+
">": operator.gt,
|
|
548
|
+
">=": operator.ge,
|
|
549
|
+
}
|
|
550
|
+
return operators[op](str(a), str(b))
|
|
551
|
+
|
|
552
|
+
def __iter__(self):
|
|
553
|
+
for item in self._items:
|
|
554
|
+
yield item
|
|
555
|
+
|
|
556
|
+
def __eq__(self, other):
|
|
557
|
+
other = self.__get_items(other)
|
|
558
|
+
return other == self._items
|
|
559
|
+
|
|
560
|
+
def __getitem__(self, item):
|
|
561
|
+
if isinstance(item, slice):
|
|
562
|
+
return self.__class__(self._items[item])
|
|
563
|
+
if isinstance(item, dict):
|
|
564
|
+
return self._items.get(item, None)
|
|
565
|
+
|
|
566
|
+
try:
|
|
567
|
+
return self._items[item]
|
|
568
|
+
except KeyError:
|
|
569
|
+
return None
|
|
570
|
+
|
|
571
|
+
def __setitem__(self, key, value):
|
|
572
|
+
self._items[key] = value
|
|
573
|
+
|
|
574
|
+
def __delitem__(self, key):
|
|
575
|
+
del self._items[key]
|
|
576
|
+
|
|
577
|
+
def __ne__(self, other):
|
|
578
|
+
other = self.__get_items(other)
|
|
579
|
+
return other != self._items
|
|
580
|
+
|
|
581
|
+
def __len__(self):
|
|
582
|
+
return len(self._items)
|
|
583
|
+
|
|
584
|
+
def __le__(self, other):
|
|
585
|
+
other = self.__get_items(other)
|
|
586
|
+
return self._items <= other
|
|
587
|
+
|
|
588
|
+
def __lt__(self, other):
|
|
589
|
+
other = self.__get_items(other)
|
|
590
|
+
return self._items < other
|
|
591
|
+
|
|
592
|
+
def __ge__(self, other):
|
|
593
|
+
other = self.__get_items(other)
|
|
594
|
+
return self._items >= other
|
|
595
|
+
|
|
596
|
+
def __gt__(self, other):
|
|
597
|
+
other = self.__get_items(other)
|
|
598
|
+
return self._items > other
|
|
599
|
+
|
|
600
|
+
@classmethod
|
|
601
|
+
def __get_items(cls, items):
|
|
602
|
+
if isinstance(items, Collection):
|
|
603
|
+
items = items.all()
|
|
604
|
+
|
|
605
|
+
return items
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .Collection import Collection
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from cleo import Command
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CanOverrideConfig(Command):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.add_option()
|
|
8
|
+
|
|
9
|
+
def add_option(self):
|
|
10
|
+
# 8 is the required flag constant in cleo
|
|
11
|
+
self._config.add_option(
|
|
12
|
+
"config",
|
|
13
|
+
"C",
|
|
14
|
+
8,
|
|
15
|
+
description="The path to the ORM configuration file. If not given DB_CONFIG_PATH env variable will be used and finally 'config.database'.",
|
|
16
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from inflection import underscore
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CanOverrideOptionsDefault:
|
|
5
|
+
"""Command mixin to allow to override optional argument default values when instantiating the
|
|
6
|
+
command.
|
|
7
|
+
Example: SomeCommand(app, option1="other/default").
|
|
8
|
+
|
|
9
|
+
If an argument long name is using - then use _ in keyword argument:
|
|
10
|
+
Example: SomeCommand(app, option_1="other/default") for an option named in option-1
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, **kwargs):
|
|
14
|
+
super().__init__()
|
|
15
|
+
self.overriden_default = kwargs
|
|
16
|
+
for option_name, option in self.config.options.items():
|
|
17
|
+
# Cleo does not authorize _ in option name but - are authorized and unfortunately -
|
|
18
|
+
# cannot be used in Python variables. So underscore() is called to make sure that
|
|
19
|
+
# an option like 'option-a' will be accessible with 'option_a' in kwargs
|
|
20
|
+
default = self.overriden_default.get(underscore(option_name))
|
|
21
|
+
if default:
|
|
22
|
+
option.set_default(default)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Craft Command.
|
|
2
|
+
|
|
3
|
+
This module is really used for backup only if the masonite CLI cannot import this for you.
|
|
4
|
+
This can be used by running "python craft". This module is not ran when the CLI can
|
|
5
|
+
successfully import commands for you.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from cleo import Application
|
|
9
|
+
|
|
10
|
+
from . import (
|
|
11
|
+
MakeMigrationCommand,
|
|
12
|
+
MakeModelCommand,
|
|
13
|
+
MakeModelDocstringCommand,
|
|
14
|
+
MakeObserverCommand,
|
|
15
|
+
MakeSeedCommand,
|
|
16
|
+
MigrateCommand,
|
|
17
|
+
MigrateFreshCommand,
|
|
18
|
+
MigrateRefreshCommand,
|
|
19
|
+
MigrateResetCommand,
|
|
20
|
+
MigrateRollbackCommand,
|
|
21
|
+
MigrateStatusCommand,
|
|
22
|
+
SeedRunCommand,
|
|
23
|
+
ShellCommand,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
application = Application("ORM Version:", 0.1)
|
|
27
|
+
|
|
28
|
+
application.add(MigrateCommand())
|
|
29
|
+
application.add(MigrateRollbackCommand())
|
|
30
|
+
application.add(MigrateRefreshCommand())
|
|
31
|
+
application.add(MigrateFreshCommand())
|
|
32
|
+
application.add(MakeMigrationCommand())
|
|
33
|
+
application.add(MakeModelCommand())
|
|
34
|
+
application.add(MakeModelDocstringCommand())
|
|
35
|
+
application.add(MakeObserverCommand())
|
|
36
|
+
application.add(MigrateResetCommand())
|
|
37
|
+
application.add(MigrateStatusCommand())
|
|
38
|
+
application.add(MakeSeedCommand())
|
|
39
|
+
application.add(SeedRunCommand())
|
|
40
|
+
application.add(ShellCommand())
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
application.run()
|