Skip to content

Commit fcd9e6e

Browse files
committed
Add operators
1 parent 55b463c commit fcd9e6e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+395
-86
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change Log
22

3+
## 13.6.0
4+
5+
* Add `total` parameter to list queries allowing skipping counting rows in a table for improved performance
6+
* Add `Operator` class for atomic modification of rows via update, bulk update, upsert, and bulk upsert operations
7+
38
## 13.5.0
49

510
* Add `create_resend_provider` and `update_resend_provider` methods to `Messaging` service

appwrite/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ def __init__(self):
1515
self._endpoint = 'https://cloud.appwrite.io/v1'
1616
self._global_headers = {
1717
'content-type': '',
18-
'user-agent' : f'AppwritePythonSDK/13.5.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})',
18+
'user-agent' : f'AppwritePythonSDK/13.6.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})',
1919
'x-sdk-name': 'Python',
2020
'x-sdk-platform': 'server',
2121
'x-sdk-language': 'python',
22-
'x-sdk-version': '13.5.0',
22+
'x-sdk-version': '13.6.0',
2323
'X-Appwrite-Response-Format' : '1.8.0',
2424
}
2525

appwrite/operator.py

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import json
2+
import math
3+
from enum import Enum
4+
5+
6+
class Condition(Enum):
7+
EQUAL = "equal"
8+
NOT_EQUAL = "notEqual"
9+
GREATER_THAN = "greaterThan"
10+
GREATER_THAN_EQUAL = "greaterThanEqual"
11+
LESS_THAN = "lessThan"
12+
LESS_THAN_EQUAL = "lessThanEqual"
13+
CONTAINS = "contains"
14+
IS_NULL = "isNull"
15+
IS_NOT_NULL = "isNotNull"
16+
17+
18+
class Operator():
19+
def __init__(self, method, values=None):
20+
self.method = method
21+
22+
if values is not None:
23+
self.values = values if isinstance(values, list) else [values]
24+
25+
def __str__(self):
26+
return json.dumps(
27+
self.__dict__,
28+
separators=(",", ":"),
29+
default=lambda obj: obj.__dict__
30+
)
31+
32+
@staticmethod
33+
def increment(value=1, max=None):
34+
if isinstance(value, float) and (math.isnan(value) or math.isinf(value)):
35+
raise ValueError("Value cannot be NaN or Infinity")
36+
if max is not None and isinstance(max, float) and (math.isnan(max) or math.isinf(max)):
37+
raise ValueError("Max cannot be NaN or Infinity")
38+
values = [value]
39+
if max is not None:
40+
values.append(max)
41+
return str(Operator("increment", values))
42+
43+
@staticmethod
44+
def decrement(value=1, min=None):
45+
if isinstance(value, float) and (math.isnan(value) or math.isinf(value)):
46+
raise ValueError("Value cannot be NaN or Infinity")
47+
if min is not None and isinstance(min, float) and (math.isnan(min) or math.isinf(min)):
48+
raise ValueError("Min cannot be NaN or Infinity")
49+
values = [value]
50+
if min is not None:
51+
values.append(min)
52+
return str(Operator("decrement", values))
53+
54+
@staticmethod
55+
def multiply(factor, max=None):
56+
if isinstance(factor, float) and (math.isnan(factor) or math.isinf(factor)):
57+
raise ValueError("Factor cannot be NaN or Infinity")
58+
if max is not None and isinstance(max, float) and (math.isnan(max) or math.isinf(max)):
59+
raise ValueError("Max cannot be NaN or Infinity")
60+
values = [factor]
61+
if max is not None:
62+
values.append(max)
63+
return str(Operator("multiply", values))
64+
65+
@staticmethod
66+
def divide(divisor, min=None):
67+
if isinstance(divisor, float) and (math.isnan(divisor) or math.isinf(divisor)):
68+
raise ValueError("Divisor cannot be NaN or Infinity")
69+
if min is not None and isinstance(min, float) and (math.isnan(min) or math.isinf(min)):
70+
raise ValueError("Min cannot be NaN or Infinity")
71+
if divisor == 0:
72+
raise ValueError("Divisor cannot be zero")
73+
values = [divisor]
74+
if min is not None:
75+
values.append(min)
76+
return str(Operator("divide", values))
77+
78+
@staticmethod
79+
def modulo(divisor):
80+
if isinstance(divisor, float) and (math.isnan(divisor) or math.isinf(divisor)):
81+
raise ValueError("Divisor cannot be NaN or Infinity")
82+
if divisor == 0:
83+
raise ValueError("Divisor cannot be zero")
84+
return str(Operator("modulo", [divisor]))
85+
86+
@staticmethod
87+
def power(exponent, max=None):
88+
if isinstance(exponent, float) and (math.isnan(exponent) or math.isinf(exponent)):
89+
raise ValueError("Exponent cannot be NaN or Infinity")
90+
if max is not None and isinstance(max, float) and (math.isnan(max) or math.isinf(max)):
91+
raise ValueError("Max cannot be NaN or Infinity")
92+
values = [exponent]
93+
if max is not None:
94+
values.append(max)
95+
return str(Operator("power", values))
96+
97+
@staticmethod
98+
def array_append(values):
99+
return str(Operator("arrayAppend", values))
100+
101+
@staticmethod
102+
def array_prepend(values):
103+
return str(Operator("arrayPrepend", values))
104+
105+
@staticmethod
106+
def array_insert(index, value):
107+
return str(Operator("arrayInsert", [index, value]))
108+
109+
@staticmethod
110+
def array_remove(value):
111+
return str(Operator("arrayRemove", [value]))
112+
113+
@staticmethod
114+
def array_unique():
115+
return str(Operator("arrayUnique", []))
116+
117+
@staticmethod
118+
def array_intersect(values):
119+
return str(Operator("arrayIntersect", values))
120+
121+
@staticmethod
122+
def array_diff(values):
123+
return str(Operator("arrayDiff", values))
124+
125+
@staticmethod
126+
def array_filter(condition, value=None):
127+
values = [condition.value if isinstance(condition, Condition) else condition, value]
128+
return str(Operator("arrayFilter", values))
129+
130+
@staticmethod
131+
def string_concat(value):
132+
return str(Operator("stringConcat", [value]))
133+
134+
@staticmethod
135+
def string_replace(search, replace):
136+
return str(Operator("stringReplace", [search, replace]))
137+
138+
@staticmethod
139+
def toggle():
140+
return str(Operator("toggle", []))
141+
142+
@staticmethod
143+
def date_add_days(days):
144+
return str(Operator("dateAddDays", [days]))
145+
146+
@staticmethod
147+
def date_sub_days(days):
148+
return str(Operator("dateSubDays", [days]))
149+
150+
@staticmethod
151+
def date_set_now():
152+
return str(Operator("dateSetNow", []))

appwrite/query.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,27 +125,27 @@ def not_ends_with(attribute, value):
125125

126126
@staticmethod
127127
def created_before(value):
128-
return str(Query("createdBefore", None, value))
128+
return Query.less_than("$createdAt", value)
129129

130130
@staticmethod
131131
def created_after(value):
132-
return str(Query("createdAfter", None, value))
132+
return Query.greater_than("$createdAt", value)
133133

134134
@staticmethod
135135
def created_between(start, end):
136-
return str(Query("createdBetween", None, [start, end]))
136+
return Query.between("$createdAt", start, end)
137137

138138
@staticmethod
139139
def updated_before(value):
140-
return str(Query("updatedBefore", None, value))
140+
return Query.less_than("$updatedAt", value)
141141

142142
@staticmethod
143143
def updated_after(value):
144-
return str(Query("updatedAfter", None, value))
144+
return Query.greater_than("$updatedAt", value)
145145

146146
@staticmethod
147147
def updated_between(start, end):
148-
return str(Query("updatedBetween", None, [start, end]))
148+
return Query.between("$updatedAt", start, end)
149149

150150
@staticmethod
151151
def or_queries(queries):

appwrite/services/account.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,16 @@ def update_email(self, email: str, password: str) -> Dict[str, Any]:
119119
'content-type': 'application/json',
120120
}, api_params)
121121

122-
def list_identities(self, queries: Optional[List[str]] = None) -> Dict[str, Any]:
122+
def list_identities(self, queries: Optional[List[str]] = None, total: Optional[bool] = None) -> Dict[str, Any]:
123123
"""
124124
Get the list of identities for the currently logged in user.
125125
126126
Parameters
127127
----------
128128
queries : Optional[List[str]]
129129
Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry
130+
total : Optional[bool]
131+
When set to false, the total count returned will be 0 and will not be calculated.
130132
131133
Returns
132134
-------
@@ -143,6 +145,7 @@ def list_identities(self, queries: Optional[List[str]] = None) -> Dict[str, Any]
143145
api_params = {}
144146

145147
api_params['queries'] = queries
148+
api_params['total'] = total
146149

147150
return self.client.call('get', api_path, {
148151
}, api_params)
@@ -201,14 +204,16 @@ def create_jwt(self) -> Dict[str, Any]:
201204
'content-type': 'application/json',
202205
}, api_params)
203206

204-
def list_logs(self, queries: Optional[List[str]] = None) -> Dict[str, Any]:
207+
def list_logs(self, queries: Optional[List[str]] = None, total: Optional[bool] = None) -> Dict[str, Any]:
205208
"""
206209
Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log.
207210
208211
Parameters
209212
----------
210213
queries : Optional[List[str]]
211214
Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset
215+
total : Optional[bool]
216+
When set to false, the total count returned will be 0 and will not be calculated.
212217
213218
Returns
214219
-------
@@ -225,6 +230,7 @@ def list_logs(self, queries: Optional[List[str]] = None) -> Dict[str, Any]:
225230
api_params = {}
226231

227232
api_params['queries'] = queries
233+
api_params['total'] = total
228234

229235
return self.client.call('get', api_path, {
230236
}, api_params)

appwrite/services/databases.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def __init__(self, client) -> None:
1212
super(Databases, self).__init__(client)
1313

1414
@deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.list` instead.")
15-
def list(self, queries: Optional[List[str]] = None, search: Optional[str] = None) -> Dict[str, Any]:
15+
def list(self, queries: Optional[List[str]] = None, search: Optional[str] = None, total: Optional[bool] = None) -> Dict[str, Any]:
1616
"""
1717
Get a list of all databases from the current Appwrite project. You can use the search parameter to filter your results.
1818
@@ -24,6 +24,8 @@ def list(self, queries: Optional[List[str]] = None, search: Optional[str] = None
2424
Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name
2525
search : Optional[str]
2626
Search term to filter your list results. Max length: 256 chars.
27+
total : Optional[bool]
28+
When set to false, the total count returned will be 0 and will not be calculated.
2729
2830
Returns
2931
-------
@@ -41,6 +43,7 @@ def list(self, queries: Optional[List[str]] = None, search: Optional[str] = None
4143

4244
api_params['queries'] = queries
4345
api_params['search'] = search
46+
api_params['total'] = total
4447

4548
return self.client.call('get', api_path, {
4649
}, api_params)
@@ -397,7 +400,7 @@ def delete(self, database_id: str) -> Dict[str, Any]:
397400
}, api_params)
398401

399402
@deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.list_tables` instead.")
400-
def list_collections(self, database_id: str, queries: Optional[List[str]] = None, search: Optional[str] = None) -> Dict[str, Any]:
403+
def list_collections(self, database_id: str, queries: Optional[List[str]] = None, search: Optional[str] = None, total: Optional[bool] = None) -> Dict[str, Any]:
401404
"""
402405
Get a list of all collections that belong to the provided databaseId. You can use the search parameter to filter your results.
403406
@@ -411,6 +414,8 @@ def list_collections(self, database_id: str, queries: Optional[List[str]] = None
411414
Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, documentSecurity
412415
search : Optional[str]
413416
Search term to filter your list results. Max length: 256 chars.
417+
total : Optional[bool]
418+
When set to false, the total count returned will be 0 and will not be calculated.
414419
415420
Returns
416421
-------
@@ -432,6 +437,7 @@ def list_collections(self, database_id: str, queries: Optional[List[str]] = None
432437

433438
api_params['queries'] = queries
434439
api_params['search'] = search
440+
api_params['total'] = total
435441

436442
return self.client.call('get', api_path, {
437443
}, api_params)
@@ -630,7 +636,7 @@ def delete_collection(self, database_id: str, collection_id: str) -> Dict[str, A
630636
}, api_params)
631637

632638
@deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.list_columns` instead.")
633-
def list_attributes(self, database_id: str, collection_id: str, queries: Optional[List[str]] = None) -> Dict[str, Any]:
639+
def list_attributes(self, database_id: str, collection_id: str, queries: Optional[List[str]] = None, total: Optional[bool] = None) -> Dict[str, Any]:
634640
"""
635641
List attributes in the collection.
636642
@@ -644,6 +650,8 @@ def list_attributes(self, database_id: str, collection_id: str, queries: Optiona
644650
Collection ID.
645651
queries : Optional[List[str]]
646652
Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, size, required, array, status, error
653+
total : Optional[bool]
654+
When set to false, the total count returned will be 0 and will not be calculated.
647655
648656
Returns
649657
-------
@@ -668,6 +676,7 @@ def list_attributes(self, database_id: str, collection_id: str, queries: Optiona
668676
api_path = api_path.replace('{collectionId}', collection_id)
669677

670678
api_params['queries'] = queries
679+
api_params['total'] = total
671680

672681
return self.client.call('get', api_path, {
673682
}, api_params)
@@ -2356,7 +2365,7 @@ def update_relationship_attribute(self, database_id: str, collection_id: str, ke
23562365
}, api_params)
23572366

23582367
@deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.list_rows` instead.")
2359-
def list_documents(self, database_id: str, collection_id: str, queries: Optional[List[str]] = None, transaction_id: Optional[str] = None) -> Dict[str, Any]:
2368+
def list_documents(self, database_id: str, collection_id: str, queries: Optional[List[str]] = None, transaction_id: Optional[str] = None, total: Optional[bool] = None) -> Dict[str, Any]:
23602369
"""
23612370
Get a list of all the user's documents in a given collection. You can use the query params to filter your results.
23622371
@@ -2372,6 +2381,8 @@ def list_documents(self, database_id: str, collection_id: str, queries: Optional
23722381
Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long.
23732382
transaction_id : Optional[str]
23742383
Transaction ID to read uncommitted changes within the transaction.
2384+
total : Optional[bool]
2385+
When set to false, the total count returned will be 0 and will not be calculated.
23752386
23762387
Returns
23772388
-------
@@ -2397,6 +2408,7 @@ def list_documents(self, database_id: str, collection_id: str, queries: Optional
23972408

23982409
api_params['queries'] = queries
23992410
api_params['transactionId'] = transaction_id
2411+
api_params['total'] = total
24002412

24012413
return self.client.call('get', api_path, {
24022414
}, api_params)
@@ -3000,7 +3012,7 @@ def increment_document_attribute(self, database_id: str, collection_id: str, doc
30003012
}, api_params)
30013013

30023014
@deprecated("This API has been deprecated since 1.8.0. Please use `tablesDB.list_indexes` instead.")
3003-
def list_indexes(self, database_id: str, collection_id: str, queries: Optional[List[str]] = None) -> Dict[str, Any]:
3015+
def list_indexes(self, database_id: str, collection_id: str, queries: Optional[List[str]] = None, total: Optional[bool] = None) -> Dict[str, Any]:
30043016
"""
30053017
List indexes in the collection.
30063018
@@ -3014,6 +3026,8 @@ def list_indexes(self, database_id: str, collection_id: str, queries: Optional[L
30143026
Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).
30153027
queries : Optional[List[str]]
30163028
Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, status, attributes, error
3029+
total : Optional[bool]
3030+
When set to false, the total count returned will be 0 and will not be calculated.
30173031
30183032
Returns
30193033
-------
@@ -3038,6 +3052,7 @@ def list_indexes(self, database_id: str, collection_id: str, queries: Optional[L
30383052
api_path = api_path.replace('{collectionId}', collection_id)
30393053

30403054
api_params['queries'] = queries
3055+
api_params['total'] = total
30413056

30423057
return self.client.call('get', api_path, {
30433058
}, api_params)

0 commit comments

Comments
 (0)