Skip to content

Commit 1547bd6

Browse files
nateshim-indicoNathanael Shim
andauthored
update submission filter (#294)
* update submission filter * update submission query * update list submissions * add tests * resolve tests * add docstrings * add test case for input_filename * address comments * fix docstring edit location * add codeowners file * Address comments * fix typing in filter init --------- Co-authored-by: Nathanael Shim <[email protected]>
1 parent dc5e982 commit 1547bd6

File tree

9 files changed

+331
-81
lines changed

9 files changed

+331
-81
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @IndicoDataSolutions/pr-be-indicodata-ai

examples/submission-filters.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from indico import IndicoClient, IndicoConfig
2+
from indico.filters import DateRangeFilter, SubmissionFilter, and_, or_
3+
from indico.queries import ListSubmissions
4+
5+
# Create an Indico API client
6+
my_config = IndicoConfig(
7+
host="try.indico.io", api_token_path="./path/to/indico_api_token.txt"
8+
)
9+
client = IndicoClient(config=my_config)
10+
11+
workflow_id = 5
12+
13+
"""
14+
Example 1
15+
List all submissions that are COMPLETE or FAILED
16+
"""
17+
sub_filter = or_(SubmissionFilter(status="COMPLETE"), SubmissionFilter(status="FAILED"))
18+
submissions = client.call(ListSubmissions(filters=sub_filter))
19+
20+
"""
21+
Example 2
22+
List all submissions that are COMPLETE and FAILED
23+
"""
24+
sub_filter = and_(
25+
SubmissionFilter(status="COMPLETE"), SubmissionFilter(status="FAILED")
26+
)
27+
submisions = client.call(ListSubmissions(filters=sub_filter))
28+
29+
"""
30+
Example 3
31+
List all submissions that are retrieved and have a filename that contains 'property'
32+
"""
33+
sub_filter = SubmissionFilter(retrieved=True, input_filename="property")
34+
submissions = client.call(ListSubmissions(filters=sub_filter))
35+
36+
"""
37+
Example 4
38+
List all submissions that are created and updated within a certain date range
39+
"""
40+
date_filter = DateRangeFilter(filter_from="2022-01-01", filter_to="2023-01-01")
41+
sub_filter = SubmissionFilter(created_at=date_filter, updated_at=date_filter)
42+
submissions = client.call(ListSubmissions(filters=sub_filter))
43+
44+
"""
45+
Example 5
46+
List all submissions that are not in progress of being reviewed and are completed
47+
"""
48+
submissions = client.call(
49+
ListSubmissions(
50+
filters=SubmissionFilter(status="COMPLETE", review_in_progress=False)
51+
)
52+
)

indico/filters/__init__.py

Lines changed: 77 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import datetime
2-
from typing import Any, Iterable, Mapping
2+
from typing import Any, Iterable, List, Mapping, Union
33

44
from indico.errors import IndicoInputError
55

@@ -48,7 +48,10 @@ class SubmissionReviewFilter(Filter):
4848
__options__ = ("rejected", "created_by", "review_type")
4949

5050
def __init__(
51-
self, rejected: bool = None, created_by: int = None, review_type: str = None
51+
self,
52+
rejected: Union[bool, None] = None,
53+
created_by: Union[int, None] = None,
54+
review_type: Union[str, None] = None,
5255
):
5356
kwargs = {
5457
"rejected": rejected,
@@ -59,33 +62,75 @@ def __init__(
5962
super().__init__(**kwargs)
6063

6164

65+
class DateRangeFilter(dict):
66+
"""
67+
Create a Filter when querying for Submissions within a certain date range
68+
Args:
69+
filter_from (str): A valid string representation of a datetime for start date to filter
70+
filter_to (str): A valid string representation of a datetime for end date to filter
71+
"""
72+
73+
def __init__(
74+
self, filter_from: Union[str, None] = None, filter_to: Union[str, None] = None
75+
):
76+
kwargs = {"from": filter_from, "to": filter_to}
77+
self.update(kwargs)
78+
79+
6280
class SubmissionFilter(Filter):
6381
"""
6482
Create a Filter when querying for WorkflowSubmissions.
6583
6684
Args:
85+
file_type (list): submissions with a file type in this list. Options:
86+
[CSV, PDF, EXCEL, DOC, DOCX, PPT, PPTX, PNG, JPG, TIFF, TXT, RTF, XLS, XLSX, UNKNOWN, MSG, EML]
6787
input_filename (str): submissions with input file names containing this string
6888
status (str): submissions in this status. Options:
6989
[PROCESSING, PENDING_REVIEW, PENDING_ADMIN_REVIEW, COMPLETE, FAILED]
70-
retrieved(bool): Filter submissions on the retrieved flag
90+
retrieved (bool): submissions that have been retrieved (True) or not (False)
91+
reviews (SubmissionReviewFilter): submissions whose completed reviews match this review filter
92+
review_in_progress (bool): submissions where a review is in progress (True) or not (False)
93+
files_deleted (bool): submissions that have had their internal files removed (True) or not (False)
94+
created_at (DateRangeFilter): submissions created during given time range
95+
updated_at (DateRangeFilter): submissions updated during given time range
7196
Returns:
7297
dict containing query filter parameters
7398
"""
7499

75-
__options__ = ("input_filename", "status", "retrieved")
100+
__options__ = (
101+
"file_type",
102+
"input_filename",
103+
"status",
104+
"retrieved",
105+
"reviews",
106+
"review_in_progress",
107+
"files_deleted",
108+
"created_at",
109+
"updated_at",
110+
)
76111

77112
def __init__(
78113
self,
79-
input_filename: str = None,
80-
status: str = None,
81-
retrieved: bool = None,
82-
reviews: SubmissionReviewFilter = None,
114+
file_type: Union[List[str], None] = None,
115+
input_filename: Union[str, None] = None,
116+
status: Union[str, None] = None,
117+
retrieved: Union[bool, None] = None,
118+
reviews: Union[SubmissionReviewFilter, None] = None,
119+
review_in_progress: Union[bool, None] = None,
120+
files_deleted: Union[bool, None] = None,
121+
created_at: Union[DateRangeFilter, None] = None,
122+
updated_at: Union[DateRangeFilter, None] = None,
83123
):
84124
kwargs = {
125+
"filetype": file_type,
85126
"inputFilename": input_filename,
86127
"status": status.upper() if status else status,
87128
"retrieved": retrieved,
88129
"reviews": reviews,
130+
"reviewInProgress": review_in_progress,
131+
"filesDeleted": files_deleted,
132+
"createdAt": created_at,
133+
"updatedAt": updated_at,
89134
}
90135

91136
super().__init__(**kwargs)
@@ -110,10 +155,10 @@ class ModelGroupExampleFilter(Filter):
110155

111156
def __init__(
112157
self,
113-
file_name: str = None,
114-
partial: bool = None,
115-
status: str = None,
116-
text_search: str = None,
158+
file_name: Union[str, None] = None,
159+
partial: Union[bool, None] = None,
160+
status: Union[str, None] = None,
161+
text_search: Union[str, None] = None,
117162
):
118163
kwargs = {
119164
"fileName": file_name,
@@ -138,7 +183,9 @@ class UserMetricsFilter(Filter):
138183

139184
__options__ = ("user_id", "user_email")
140185

141-
def __init__(self, user_id: int = None, user_email: str = None):
186+
def __init__(
187+
self, user_id: Union[int, None] = None, user_email: Union[str, None] = None
188+
):
142189
kwargs = {"userId": user_id, "userEmail": user_email}
143190

144191
super().__init__(**kwargs)
@@ -172,32 +219,36 @@ class DocumentReportFilter(Filter):
172219

173220
def __init__(
174221
self,
175-
submission_id: int = None,
176-
workflow_id: int = None,
177-
status: str = None,
178-
created_at_start_date: datetime = None,
179-
created_at_end_date: datetime = None,
180-
updated_at_start_date: datetime = None,
181-
updated_at_end_date: datetime = None,
222+
submission_id: Union[int, None] = None,
223+
workflow_id: Union[int, None] = None,
224+
status: Union[str, None] = None,
225+
created_at_start_date: Union[datetime.datetime, None] = None,
226+
created_at_end_date: Union[datetime.datetime, None] = None,
227+
updated_at_start_date: Union[datetime.datetime, None] = None,
228+
updated_at_end_date: Union[datetime.datetime, None] = None,
182229
):
183230
kwargs = {"workflowId": workflow_id, "id": submission_id, "status": status}
184231
if created_at_end_date and not created_at_start_date:
185232
raise IndicoInputError("Must specify created_at_start_date")
186233
if created_at_start_date:
187234
kwargs["createdAt"] = {
188235
"from": created_at_start_date.strftime("%Y-%m-%d"),
189-
"to": created_at_end_date.strftime("%Y-%m-%d")
190-
if created_at_end_date is not None
191-
else datetime.datetime.now().strftime("%Y-%m-%d"),
236+
"to": (
237+
created_at_end_date.strftime("%Y-%m-%d")
238+
if created_at_end_date is not None
239+
else datetime.datetime.now().strftime("%Y-%m-%d")
240+
),
192241
}
193242

194243
if updated_at_end_date and not updated_at_start_date:
195244
raise IndicoInputError("Must specify updated_at_start_date")
196245
if updated_at_start_date is not None:
197246
kwargs["updatedAt"] = {
198247
"from": updated_at_start_date.strftime("%Y-%m-%d"),
199-
"to": updated_at_end_date.strftime("%Y-%m-%d")
200-
if updated_at_end_date is not None
201-
else datetime.datetime.now().strftime("%Y-%m-%d"),
248+
"to": (
249+
updated_at_end_date.strftime("%Y-%m-%d")
250+
if updated_at_end_date is not None
251+
else datetime.datetime.now().strftime("%Y-%m-%d")
252+
),
202253
}
203254
super().__init__(**kwargs)

indico/queries/submission.py

Lines changed: 77 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -33,57 +33,91 @@ class ListSubmissions(PagedRequest):
3333

3434
query = """
3535
query ListSubmissions(
36-
$submissionIds: [Int],
37-
$workflowIds: [Int],
38-
$filters: SubmissionFilter,
39-
$limit: Int,
40-
$orderBy: SUBMISSION_COLUMN_ENUM,
41-
$desc: Boolean,
36+
$submissionIds: [Int]
37+
$workflowIds: [Int]
38+
$filters: SubmissionFilter
39+
$limit: Int
40+
$orderBy: SUBMISSION_COLUMN_ENUM
41+
$desc: Boolean
4242
$after: Int
43-
44-
){
43+
) {
4544
submissions(
46-
submissionIds: $submissionIds,
47-
workflowIds: $workflowIds,
48-
filters: $filters,
45+
submissionIds: $submissionIds
46+
workflowIds: $workflowIds
47+
filters: $filters
4948
limit: $limit
50-
orderBy: $orderBy,
51-
desc: $desc,
49+
orderBy: $orderBy
50+
desc: $desc
5251
after: $after
53-
54-
){
52+
) {
5553
submissions {
54+
id
55+
datasetId
56+
workflowId
57+
status
58+
createdAt
59+
updatedAt
60+
createdBy
61+
updatedBy
62+
completedAt
63+
errors
64+
filesDeleted
65+
inputFiles {
5666
id
57-
datasetId
58-
workflowId
59-
status
60-
inputFiles {
61-
id
62-
filename
63-
filepath
64-
filetype
65-
fileSize
66-
numPages
67-
}
68-
inputFile
69-
inputFilename
70-
resultFile
71-
deleted
72-
retrieved
73-
errors
74-
reviews {
75-
id
76-
createdAt
77-
createdBy
78-
completedAt
79-
rejected
80-
reviewType
81-
notes
82-
}
67+
filepath
68+
filename
69+
filetype
70+
submissionId
71+
fileSize
72+
numPages
73+
}
74+
inputFile
75+
inputFilename
76+
resultFile
77+
outputFiles {
78+
id
79+
filepath
80+
submissionId
81+
componentId
82+
createdAt
83+
}
84+
retrieved
85+
autoReview {
86+
id
87+
submissionId
88+
createdAt
89+
createdBy
90+
startedAt
91+
completedAt
92+
rejected
93+
reviewType
94+
notes
95+
}
96+
retries {
97+
id
98+
submissionId
99+
previousErrors
100+
previousStatus
101+
retryErrors
102+
}
103+
reviews {
104+
id
105+
submissionId
106+
createdAt
107+
createdBy
108+
startedAt
109+
completedAt
110+
rejected
111+
reviewType
112+
notes
113+
}
114+
reviewInProgress
83115
}
84116
pageInfo {
85-
endCursor
86-
hasNextPage
117+
startCursor
118+
endCursor
119+
hasNextPage
120+
aggregateCount
87121
}
88122
}
89123
}

indico/types/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .jobs import *
44
from .model_group import *
55
from .model import *
6+
from .output_file import *
67
from .submission_file import *
78
from .submission import *
89
from .workflow import *

indico/types/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def __init__(self, **kwargs):
4444
k = cc_to_snake(k)
4545
if k in attrs:
4646
attr_type = attrs[k]
47-
if inspect.isclass(attr_type) and issubclass(attr_type, BaseType):
47+
if v is not None and inspect.isclass(attr_type) and issubclass(attr_type, BaseType):
4848
v = attrs[k](**v)
4949

5050
if attr_type == JSONType:

0 commit comments

Comments
 (0)