Skip to content

Commit b159769

Browse files
authored
Promote 223 from Deploy test (#225)
* modify resolver logic; new Union for resolver; test w ScaledInversionSolution * fix test queries impacted by new InversionSolutionUnion * update changelog * Bump version: 0.2.1 → 0.2.2
1 parent b91f124 commit b159769

11 files changed

+194
-23
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.2.1
2+
current_version = 0.2.2
33
commit = True
44
tag = False
55

CHANGELOG.md

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

3+
## [0.2.2] - 2024-06-27
4+
### Changed
5+
- Schema.nodes resolver now handles all InversionSolution types
6+
- AutomationTask.inversion_solution resolver now handles all InversionSolution types
7+
38
## [0.2.1] - 2024-06-20
49

510
### Changed

graphql_api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
__author__ = 'GNS Science'
44
__email__ = 'nshm@gns.cri.nz'
5-
__version__ = '0.2.1'
5+
__version__ = '0.2.2'

graphql_api/schema/custom/automation_task.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ class Meta:
4646
model_type = ModelType()
4747
task_type = TaskSubType()
4848
inversion_solution = graphene.Field(
49-
'graphql_api.schema.custom.inversion_solution.InversionSolution',
50-
description="the primary result of this task (only for task_type == INVERSION.",
49+
'graphql_api.schema.custom.inversion_solution_union.InversionSolutionUnion',
50+
description="the result of this task. NB only available for task_types:"
51+
"INVERSION, SCALE_SOLUTION, AGGREGATE_SOLUTION, TIME_DEPENDENT_SOLUTION.",
5152
)
5253

5354
@staticmethod
@@ -56,16 +57,27 @@ def from_json(jsondata):
5657

5758
@staticmethod
5859
def resolve_inversion_solution(root, info, **args):
60+
61+
log.info(f"resolve_inversion_solution {root.task_type}")
62+
resolvable_types = [
63+
TaskSubType.INVERSION.value,
64+
TaskSubType.SCALE_SOLUTION.value,
65+
TaskSubType.AGGREGATE_SOLUTION.value,
66+
TaskSubType.TIME_DEPENDENT_SOLUTION.value,
67+
]
68+
5969
if not len(root.files):
6070
return
61-
if not root.task_type == TaskSubType.INVERSION.value:
71+
if root.task_type not in resolvable_types:
72+
log.info(f"Cannot resove inversion_soluton for {root.task_type}")
6273
return
6374

6475
t0 = dt.utcnow()
6576
res = None
6677

6778
# TODO this is an ugly hack....
68-
# - It gets the inversion solution by traversing the file_relations until it finds an InversionSolution.
79+
# - It gets the inversion solution by traversing the file_relations until it finds
80+
# an InversionSolution subtype.
6981
# - Instead this attribute needs to be a first-class one-to-one relationship
7082
for file_id in root.files:
7183
if isinstance(file_id, dict): # new form, files is list of objects
@@ -79,9 +91,11 @@ def resolve_inversion_solution(root, info, **args):
7991
if not file_relation.role == FileRole.WRITE.value:
8092
continue
8193
file = get_data_manager().file.get_one(file_relation.file_id)
82-
if file.__class__.__name__ == 'InversionSolution':
94+
if 'InversionSolution' in file.__class__.__name__:
8395
res = file
96+
log.info(f"resolved inversion_solution file {file}")
8497
break
98+
8599
db_metrics.put_duration(__name__, 'AutomationTask.resolve_inversion_solution', dt.utcnow() - t0)
86100
return res
87101

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# !inversion_solution_union.py
2+
import graphene
3+
4+
from .aggregate_inversion_solution import AggregateInversionSolution
5+
from .inversion_solution import InversionSolution
6+
from .scaled_inversion_solution import ScaledInversionSolution
7+
from .time_dependent_inversion_solution import TimeDependentInversionSolution
8+
9+
10+
class InversionSolutionUnion(graphene.Union):
11+
class Meta:
12+
types = (
13+
InversionSolution,
14+
ScaledInversionSolution,
15+
AggregateInversionSolution,
16+
TimeDependentInversionSolution,
17+
)

graphql_api/tests/legacy/test_automation_task_related_solution.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ def test_task_product_query(self, mocked_api_DB):
140140
id
141141
created
142142
inversion_solution {
143-
id
144-
file_name
143+
... on Node { id }
144+
... on FileInterface { file_name }
145145
}
146146
files {
147147
total_count
@@ -183,8 +183,8 @@ def test_example_failing_product_query(self, mocked_api_DB):
183183
id
184184
created
185185
inversion_solution {
186-
id
187-
file_name
186+
... on Node { id }
187+
... on FileInterface { file_name }
188188
}
189189
files {
190190
total_count

graphql_api/tests/simpler_relationships/test_automation_task_related_solution_new.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ def test_task_product_query(self, mocked_api):
115115
id
116116
created
117117
inversion_solution {
118-
id
119-
file_name
118+
... on Node { id }
119+
... on FileInterface { file_name }
120120
}
121121
files {
122122
total_count
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""
2+
Test API function for GeneralTask
3+
using moto mocking re issue #223
4+
"""
5+
6+
import datetime as dt
7+
import unittest
8+
9+
import boto3
10+
from dateutil.tz import tzutc
11+
from graphene.test import Client
12+
from graphql_relay import from_global_id
13+
from moto import mock_dynamodb, mock_s3
14+
from pynamodb.connection.base import Connection # for mocking
15+
16+
from graphql_api.config import REGION, S3_BUCKET_NAME
17+
from graphql_api.data import data_manager
18+
from graphql_api.dynamodb.models import ToshiFileObject, ToshiIdentity, ToshiThingObject
19+
from graphql_api.schema import root_schema
20+
from graphql_api.schema.search_manager import SearchManager
21+
22+
from .hazard.setup_helpers import SetupHelpersMixin
23+
24+
25+
@mock_dynamodb
26+
@mock_s3
27+
class TestScaledInversionSolution(unittest.TestCase, SetupHelpersMixin):
28+
def setUp(self):
29+
self.client = Client(root_schema)
30+
31+
# S3
32+
self._s3 = boto3.resource('s3', region_name=REGION)
33+
self._s3.create_bucket(Bucket=S3_BUCKET_NAME)
34+
35+
# Dynamo
36+
self._connection = Connection(region=REGION)
37+
38+
ToshiThingObject.create_table()
39+
ToshiFileObject.create_table()
40+
ToshiIdentity.create_table()
41+
42+
self._data_manager = data_manager.DataManager(search_manager=SearchManager('test', 'test', {'fake': 'auth'}))
43+
44+
upstream_sid = self.create_source_solution()
45+
self.new_gt = self.create_general_task()
46+
self.at_id = self.create_automation_task("SCALE_SOLUTION")
47+
self.create_gt_relation(self.new_gt, self.at_id)
48+
49+
result = self.create_scaled_solution(upstream_sid, self.at_id)
50+
51+
ss = result['data']['create_scaled_inversion_solution']['solution']
52+
self.scaled_solution_id = ss['id']
53+
54+
# def create_task_file(self, task_id, file_id, role):
55+
qry2 = '''
56+
mutation create_file_relation(
57+
$thing_id:ID!
58+
$file_id:ID!
59+
$role:FileRole!) {
60+
create_file_relation(
61+
file_id:$file_id
62+
thing_id:$thing_id
63+
role:$role
64+
)
65+
{
66+
ok
67+
}
68+
}'''
69+
variables = dict(thing_id=self.at_id, file_id=self.at_id, role='WRITE')
70+
executed = self.client.execute(qry2, variable_values=variables)
71+
print('created file relation', executed)
72+
73+
def test_general_task_query(self):
74+
print("self.new_gt", self.new_gt)
75+
76+
qry = '''
77+
query GeneralTaskChildrenTabQuery($id: ID!) {
78+
node(id: $id) {
79+
... on GeneralTask {
80+
id
81+
model_type
82+
children {
83+
edges {
84+
node {
85+
child {
86+
__typename
87+
... on Node {
88+
id
89+
}
90+
...on AutomationTask {
91+
task_type
92+
inversion_solution {
93+
__typename
94+
... on Node {
95+
id
96+
}
97+
}
98+
}
99+
... on AutomationTaskInterface {
100+
state
101+
result
102+
created
103+
duration
104+
arguments {
105+
k
106+
v
107+
}
108+
}
109+
}
110+
}
111+
}
112+
}
113+
}
114+
}
115+
}
116+
117+
'''
118+
119+
print(qry)
120+
executed = self.client.execute(qry, variable_values=dict(id=self.new_gt))
121+
print(executed)
122+
123+
node = executed['data']['node']
124+
assert node['id'] == self.new_gt
125+
assert node['children']['edges'][0]['node']['child']['__typename'] == "AutomationTask"
126+
assert node['children']['edges'][0]['node']['child']['inversion_solution']['__typename']
127+
assert node['children']['edges'][0]['node']['child']['inversion_solution']['id'] == self.scaled_solution_id
128+
assert (
129+
node['children']['edges'][0]['node']['child']['inversion_solution']['__typename']
130+
== "ScaledInversionSolution"
131+
)

graphql_api/tests/test_inversion_solution_bug_93.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,19 @@ def test_query_with_files(self, mocked_read_object, mocked_get_one):
148148
task_type
149149
id
150150
inversion_solution {
151-
id
152-
file_name
153-
meta {
154-
k
155-
v
151+
... on Node { id }
152+
... on FileInterface {
153+
file_name
154+
meta {
155+
k
156+
v
157+
}
156158
}
157-
tables {
158-
table_id
159-
table_type
159+
... on InversionSolutionInterface {
160+
tables {
161+
table_id
162+
table_type
163+
}
160164
}
161165
}
162166
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nzshm22-toshi-api",
3-
"version": "0.2.1",
3+
"version": "0.2.2",
44
"description": "A graphql API for NZSHM22 shared resources using AWS lambda, S3, Dynamodb and ElasticSearch",
55
"directories": {
66
"lib": "lib"

0 commit comments

Comments
 (0)