Skip to content

Commit 91c7f46

Browse files
Narek MkhitaryanNarek Mkhitaryan
authored andcommitted
updates in user/project list
1 parent 8bfb772 commit 91c7f46

File tree

7 files changed

+109
-45
lines changed

7 files changed

+109
-45
lines changed

src/superannotate/lib/core/jsx_conditions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ class OperatorEnum(str, Enum):
1313
EQ = "$eq"
1414
NE = "$ne"
1515
GT = "$gt"
16+
GTE = "$gte"
1617
LT = "$lt"
18+
LTE = "$lte"
1719
IS = "$is"
1820
CONTAINS = "$cont"
1921
STARTS = "$starts"

src/superannotate/lib/infrastructure/controller.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,15 @@ def set_custom_field_value(
162162
)
163163

164164
def list_users(self, include: List[Literal["custom_fields"]] = None, **filters):
165+
valid_fields = generate_schema(
166+
UserFilters.__annotations__,
167+
self.service_provider.get_custom_fields_templates(
168+
CustomFieldEntityEnum.CONTRIBUTOR
169+
),
170+
)
165171
chain = QueryBuilderChain(
166172
[
167-
FieldValidationHandler(UserFilters.__annotations__.keys()),
173+
FieldValidationHandler(valid_fields.keys()),
168174
UserFilterHandler(
169175
service_provider=self.service_provider,
170176
entity=CustomFieldEntityEnum.CONTRIBUTOR,

src/superannotate/lib/infrastructure/custom_entities.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,34 @@
1010
OperatorEnum.NOTIN,
1111
OperatorEnum.CONTAINS,
1212
],
13-
CustomFieldType.MULTI_SELECT: [OperatorEnum.EQ, OperatorEnum.NOTIN],
13+
CustomFieldType.MULTI_SELECT: [
14+
OperatorEnum.EQ,
15+
OperatorEnum.NOTIN,
16+
OperatorEnum.IN,
17+
],
1418
CustomFieldType.SINGLE_SELECT: [
1519
OperatorEnum.EQ,
1620
OperatorEnum.IN,
1721
OperatorEnum.NOTIN,
1822
OperatorEnum.CONTAINS,
1923
],
20-
CustomFieldType.DATE_PICKER: [OperatorEnum.GT, OperatorEnum.LT, OperatorEnum.EQ],
24+
CustomFieldType.DATE_PICKER: [
25+
OperatorEnum.GT,
26+
OperatorEnum.LT,
27+
OperatorEnum.GTE,
28+
OperatorEnum.LTE,
29+
OperatorEnum.EQ,
30+
],
2131
CustomFieldType.NUMERIC: [
2232
OperatorEnum.GT,
2333
OperatorEnum.LT,
2434
OperatorEnum.EQ,
35+
OperatorEnum.NE,
2536
OperatorEnum.IN,
2637
OperatorEnum.NOTIN,
2738
],
2839
}
2940

30-
# todo implement
31-
FIELD_TYPE_BED_OPERATIONS_MAPPING = {
32-
CustomFieldType.MULTI_SELECT: {OperatorEnum.EQ: OperatorEnum.IN},
33-
CustomFieldType.DATE_PICKER: {OperatorEnum.EQ: OperatorEnum.IS},
34-
}
35-
3641

3742
def generate_schema(base_schema: dict, custom_field_templates) -> dict:
3843
annotations = base_schema

src/superannotate/lib/infrastructure/query_builder.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,20 @@ def _handle_custom_field_key(self, key) -> Tuple[str, str, Optional[str]]:
109109
reverse=True,
110110
):
111111
if custom_field in key:
112-
return key.replace(
112+
custom_field_id = self._service_provider.get_custom_field_id(
113+
custom_field, entity=self._entity
114+
)
115+
component_id = self._service_provider.get_custom_field_component_id(
116+
custom_field_id, entity=self._entity
117+
)
118+
key = key.replace(
113119
custom_field,
114-
str(
115-
self._service_provider.get_custom_field_id(
116-
custom_field, entity=self._entity
117-
)
118-
),
120+
str(custom_field_id),
119121
).split("__")
122+
# in case multi_select replace EQ to IN (BED requirement)
123+
if component_id == CustomFieldType.MULTI_SELECT.value and len(key) == 2:
124+
key.append(OperatorEnum.IN.name)
125+
return key
120126
raise AppException("Invalid custom field name provided.")
121127

122128
@staticmethod

src/superannotate/lib/infrastructure/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ def sync(self, **kwargs):
6565
raise NotImplementedError
6666

6767
def get(self, key, **kwargs):
68-
self.sync(**kwargs)
68+
if not self._is_cache_valid(key):
69+
self.sync(**kwargs)
6970
return self._K_V_map[key]
7071

7172

@@ -143,7 +144,8 @@ def sync(self, team_id):
143144
self._update_cache_timestamp(team_id)
144145

145146
def get(self, key, **kwargs):
146-
self.sync(team_id=key)
147+
if not self._is_cache_valid(key):
148+
self.sync(team_id=key)
147149
return self._K_V_map[key]
148150

149151

tests/integration/work_management/test_project_custom_fields.py

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import time
12
from typing import Any
23
from typing import Dict
34

@@ -131,6 +132,7 @@ def test_set_project_custom_field_validation(
131132
self.PROJECT_NAME, "SDK_test_single_select", 123
132133
)
133134

135+
# TODO BED issue ("projects/search" endpoint return other teams projects)
134136
def test_list_projects_by_native_fields(self):
135137
projects = sa.list_projects(name=self.PROJECT_NAME)
136138
assert len(projects) == 1
@@ -237,23 +239,28 @@ def test_list_projects_by_custom_fields(self):
237239
len(
238240
sa.list_projects(
239241
include=["custom_fields"],
240-
custom_field__SDK_test_multi_select__in=["option1"],
242+
custom_field__SDK_test_date_picker__gte=time.time(),
241243
)
242244
)
243-
== 1
245+
== 0
244246
)
245247
assert (
246248
len(
247249
sa.list_projects(
248250
include=["custom_fields"],
249-
custom_field__SDK_test_multi_select__in=["option1", "option2"],
251+
custom_field__SDK_test_date_picker__lte=time.time(),
250252
)
251253
)
252254
== 1
253255
)
254-
255-
self._set_custom_field_values(
256-
{"SDK_test_multi_select": ["option1", "option2", "option3"]}
256+
assert (
257+
len(
258+
sa.list_projects(
259+
include=["custom_fields"],
260+
custom_field__SDK_test_multi_select__in=["option1"],
261+
)
262+
)
263+
== 1
257264
)
258265
assert (
259266
len(
@@ -264,26 +271,28 @@ def test_list_projects_by_custom_fields(self):
264271
)
265272
== 1
266273
)
274+
# multi select EQ case
267275
assert (
268276
len(
269277
sa.list_projects(
270278
include=["custom_fields"],
271-
custom_field__SDK_test_multi_select__contains="option3",
279+
custom_field__SDK_test_multi_select=["option1", "option2"],
272280
)
273281
)
274282
== 1
275283
)
284+
285+
self._set_custom_field_values(
286+
{"SDK_test_multi_select": ["option1", "option2", "option3"]}
287+
)
276288
assert (
277289
len(
278290
sa.list_projects(
279291
include=["custom_fields"],
280-
custom_field__SDK_test_multi_select__contains=[
281-
"option3",
282-
"option1",
283-
],
292+
custom_field__SDK_test_multi_select__in=["option1", "option2"],
284293
)
285294
)
286-
== 0
295+
== 1
287296
)
288297
assert (
289298
len(
@@ -298,15 +307,11 @@ def test_list_projects_by_custom_fields(self):
298307
len(
299308
sa.list_projects(
300309
include=["custom_fields"],
301-
custom_field__SDK_test_multi_select__contains="option2",
310+
custom_field__SDK_test_single_select__contains="option1",
302311
)
303312
)
304313
== 1
305314
)
306-
assert not sa.list_projects(
307-
include=["custom_fields"],
308-
custom_field__SDK_test_multi_select__contains="invalid_option",
309-
)
310315
assert (
311316
len(
312317
sa.list_projects(
@@ -318,9 +323,7 @@ def test_list_projects_by_custom_fields(self):
318323
)
319324

320325
def test_list_projects_by_custom_invalid_field(self):
321-
with self.assertRaisesRegexp(
322-
AppException, "Invalid custom field name provided."
323-
):
326+
with self.assertRaisesRegexp(AppException, "Invalid filter param provided."):
324327
sa.list_projects(
325328
include=["custom_fields"],
326329
custom_field__INVALID_FIELD="text",
@@ -338,11 +341,3 @@ def test_list_projects_by_status_in(self):
338341
]
339342
assert len(set(all_team_ids)) == 1
340343
assert all_team_ids[0] == sa.controller.team_id
341-
342-
# TODO BED issue (in case multiselect exact match)
343-
def test_list_projects_by_multi_select_eq(self):
344-
self._set_custom_field_values()
345-
sa.list_projects(
346-
include=["custom_fields"],
347-
custom_field__SDK_test_multi_select=["option1", "option2"],
348-
)

tests/integration/work_management/test_user_custom_fields.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def test_get_set_user_metadata(self):
5151
users = sa.list_users()
5252
scapegoat = [u for u in users if u["role"] == "Contributor"][0]
5353
assert not scapegoat["custom_fields"]
54+
# text field
5455
sa.set_user_custom_field(
5556
scapegoat["email"],
5657
custom_field_name="SDK_test_text",
@@ -70,6 +71,53 @@ def test_get_set_user_metadata(self):
7071
assert len(users) == 1
7172
assert users[0]["custom_fields"]["SDK_test_text"] == "Dummy data"
7273

74+
# multi select field
75+
sa.set_user_custom_field(
76+
scapegoat["email"],
77+
custom_field_name="SDK_test_multi_select",
78+
value=["option1", "option2"],
79+
)
80+
assert (
81+
len(
82+
sa.list_users(
83+
include=["custom_fields"],
84+
custom_field__SDK_test_multi_select=["option1", "option2"],
85+
)
86+
)
87+
== 1
88+
)
89+
90+
# single select field
91+
sa.set_user_custom_field(
92+
scapegoat["email"],
93+
custom_field_name="SDK_test_single_select",
94+
value="option1",
95+
)
96+
assert (
97+
len(
98+
sa.list_users(
99+
include=["custom_fields"],
100+
custom_field__SDK_test_single_select__contains="option1",
101+
)
102+
)
103+
== 1
104+
)
105+
106+
# numeric field
107+
sa.set_user_custom_field(
108+
scapegoat["email"],
109+
custom_field_name="SDK_test_numeric",
110+
value=5,
111+
)
112+
assert (
113+
len(
114+
sa.list_users(
115+
include=["custom_fields"], custom_field__SDK_test_numeric__lt=10
116+
)
117+
)
118+
== 1
119+
)
120+
73121
def test_list_users(self):
74122
users = sa.list_users()
75123
all_contributors = [u for u in users if u["role"] == "Contributor"]

0 commit comments

Comments
 (0)