Skip to content

Commit

Permalink
Merge pull request #24 from LCOGT/direct_request_details
Browse files Browse the repository at this point in the history
display proper fields for direct type observation on request details …
  • Loading branch information
jnation3406 committed Jun 12, 2019
2 parents 61efe50 + a7b7f6d commit eb9acd3
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 52 deletions.
6 changes: 4 additions & 2 deletions observation_portal/common/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def __exit__(self, type, value, traceback):
def create_simple_requestgroup(user, proposal, state='PENDING', request=None, window=None, configuration=None,
constraints=None, target=None, location=None, instrument_config=None,
acquisition_config=None, guiding_config=None, instrument_type=None):
rg = mixer.blend(RequestGroup, state=state, submitter=user, proposal=proposal)
rg = mixer.blend(RequestGroup, state=state, submitter=user, proposal=proposal,
observation_type=RequestGroup.NORMAL)

if not request:
request = mixer.blend(Request, request_group=rg)
Expand Down Expand Up @@ -83,7 +84,8 @@ def create_simple_requestgroup(user, proposal, state='PENDING', request=None, wi

def create_simple_many_requestgroup(user, proposal, n_requests, state='PENDING'):
operator = 'SINGLE' if n_requests == 1 else 'MANY'
rg = mixer.blend(RequestGroup, state=state, submitter=user, proposal=proposal, operator=operator)
rg = mixer.blend(RequestGroup, state=state, submitter=user, proposal=proposal, operator=operator,
observation_type=RequestGroup.NORMAL)
for i in range(n_requests):
request = mixer.blend(Request, request_group=rg, state=state)
mixer.blend(Window, request=request)
Expand Down
14 changes: 7 additions & 7 deletions observation_portal/common/test_state_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,42 +668,42 @@ def test_request_state_configuration_status_failed_2(self):
class TestAggregateRequestStates(TestCase):
def test_many_all_complete(self):
request_states = ['COMPLETED', 'COMPLETED', 'COMPLETED']
rg = dmixer.blend(RequestGroup, operator='MANY')
rg = dmixer.blend(RequestGroup, operator='MANY', observation_type=RequestGroup.NORMAL)
dmixer.cycle(3).blend(Request, state=(state for state in request_states), request_group=rg)
aggregate_state = aggregate_request_states(rg)
self.assertEqual(aggregate_state, 'COMPLETED')

def test_many_any_pending(self):
request_states = ['COMPLETED', 'CANCELED', 'PENDING']
rg = dmixer.blend(RequestGroup, operator='MANY')
rg = dmixer.blend(RequestGroup, operator='MANY', observation_type=RequestGroup.NORMAL)
dmixer.cycle(3).blend(Request, state=(state for state in request_states), request_group=rg)
aggregate_state = aggregate_request_states(rg)
self.assertEqual(aggregate_state, 'PENDING')

def test_many_expired_and_complete(self):
request_states = ['WINDOW_EXPIRED', 'COMPLETED', 'WINDOW_EXPIRED']
rg = dmixer.blend(RequestGroup, operator='MANY')
rg = dmixer.blend(RequestGroup, operator='MANY', observation_type=RequestGroup.NORMAL)
dmixer.cycle(3).blend(Request, state=(state for state in request_states), request_group=rg)
aggregate_state = aggregate_request_states(rg)
self.assertEqual(aggregate_state, 'COMPLETED')

def test_many_canceled_and_complete(self):
request_states = ['CANCELED', 'COMPLETED', 'CANCELED']
rg = dmixer.blend(RequestGroup, operator='MANY')
rg = dmixer.blend(RequestGroup, operator='MANY', observation_type=RequestGroup.NORMAL)
dmixer.cycle(3).blend(Request, state=(state for state in request_states), request_group=rg)
aggregate_state = aggregate_request_states(rg)
self.assertEqual(aggregate_state, 'COMPLETED')

def test_many_all_canceled(self):
request_states = ['CANCELED', 'CANCELED', 'CANCELED']
rg = dmixer.blend(RequestGroup, operator='MANY')
rg = dmixer.blend(RequestGroup, operator='MANY', observation_type=RequestGroup.NORMAL)
dmixer.cycle(3).blend(Request, state=(state for state in request_states), request_group=rg)
aggregate_state = aggregate_request_states(rg)
self.assertEqual(aggregate_state, 'CANCELED')

def test_many_all_expired(self):
request_states = ['WINDOW_EXPIRED', 'WINDOW_EXPIRED', 'WINDOW_EXPIRED']
rg = dmixer.blend(RequestGroup, operator='MANY')
rg = dmixer.blend(RequestGroup, operator='MANY', observation_type=RequestGroup.NORMAL)
dmixer.cycle(3).blend(Request, state=(state for state in request_states), request_group=rg)
aggregate_state = aggregate_request_states(rg)
self.assertEqual(aggregate_state, 'WINDOW_EXPIRED')
Expand All @@ -712,7 +712,7 @@ def test_many_all_expired(self):
@patch('observation_portal.common.state_changes.modify_ipp_time_from_requests')
class TestExpireRequests(TestCase):
def setUp(self):
self.request_group = dmixer.blend(RequestGroup, state='PENDING')
self.request_group = dmixer.blend(RequestGroup, state='PENDING', observation_type=RequestGroup.NORMAL)

def test_request_is_set_to_expired(self, ipp_mock):
request = dmixer.blend(Request, state='PENDING', request_group=self.request_group)
Expand Down
3 changes: 2 additions & 1 deletion observation_portal/proposals/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ def setUp(self):
self.proposal = mixer.blend(Proposal)
self.user = mixer.blend(User)
mixer.blend(Membership, user=self.user, proposal=self.proposal)
self.requestgroup = mixer.blend(RequestGroup, proposal=self.proposal, submitter=self.user, state='PENDING')
self.requestgroup = mixer.blend(RequestGroup, proposal=self.proposal, submitter=self.user, state='PENDING',
observation_type=RequestGroup.NORMAL)

def test_all_proposal_notification(self):
mixer.blend(Profile, user=self.user, notifications_enabled=True)
Expand Down
10 changes: 8 additions & 2 deletions observation_portal/requestgroups/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,14 @@ def as_dict(self, for_observation=False):
ret_dict['duration'] = self.duration
ret_dict['configurations'] = [c.as_dict() for c in self.configurations.all()]
if not for_observation:
ret_dict['location'] = self.location.as_dict()
ret_dict['windows'] = [w.as_dict() for w in self.windows.all()]
if self.request_group.observation_type == RequestGroup.DIRECT:
observation = self.observation_set.first()
ret_dict['location'] = {'site': observation.site, 'enclosure': observation.enclosure,
'telescope': observation.telescope}
ret_dict['windows'] = [{'start': observation.start, 'end': observation.end}]
else:
ret_dict['location'] = self.location.as_dict() if hasattr(self, 'location') else {}
ret_dict['windows'] = [w.as_dict() for w in self.windows.all()]
return ret_dict

@cached_property
Expand Down
20 changes: 11 additions & 9 deletions observation_portal/requestgroups/request_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,30 @@
}


def get_telescope_states_for_request(request):
def get_telescope_states_for_request(request_dict):
# TODO: update to support multiple instruments in a list
instrument_type = request.configurations.first().instrument_type
instrument_type = request_dict['configurations'][0]['instrument_type']
site_intervals = {}
# Build up the list of telescopes and their rise set intervals for the target on this request
site_data = configdb.get_sites_with_instrument_type_and_location(
instrument_type=instrument_type,
site_code=request.location.site,
enclosure_code=request.location.enclosure,
telescope_code=request.location.telescope
site_code=request_dict['location']['site'] if 'site' in request_dict['location'] else '',
enclosure_code=request_dict['location']['enclosure'] if 'enclosure' in request_dict['location'] else '',
telescope_code=request_dict['location']['telescope'] if 'telescope' in request_dict['location'] else ''
)
for site, details in site_data.items():
if site not in site_intervals:
site_intervals[site] = get_filtered_rise_set_intervals_by_site(request.as_dict(), site).get(site, [])
site_intervals[site] = get_filtered_rise_set_intervals_by_site(request_dict, site).get(site, [])
# If you have no sites, return the empty dict here
if not site_intervals:
return {}

# Retrieve the telescope states for that set of sites
min_window_time = min([window['start'] for window in request_dict['windows']])
max_window_time = max([window['end'] for window in request_dict['windows']])
telescope_states = TelescopeStates(
start=request.min_window_time,
end=request.max_window_time,
start=min_window_time,
end=max_window_time,
sites=list(site_intervals.keys()),
instrument_types=[instrument_type]
).get()
Expand All @@ -56,7 +58,7 @@ def get_telescope_states_for_request(request):

# Filter the telescope states list with the site intervals
filtered_telescope_states = filter_telescope_states_by_intervals(
telescope_states, site_intervals, request.min_window_time, request.max_window_time
telescope_states, site_intervals, min_window_time, max_window_time
)

return filtered_telescope_states
Expand Down
6 changes: 4 additions & 2 deletions observation_portal/requestgroups/test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ def setUp(self):
instrument_type='1M0-SCICAM-SBIG', rr_allocation=10, rr_time_used=0.0, ipp_limit=10.0,
ipp_time_available=5.0
)
self.rg_single = mixer.blend(RequestGroup, proposal=self.proposal, operator='SINGLE')
self.rg_many = mixer.blend(RequestGroup, proposal=self.proposal)
self.rg_single = mixer.blend(RequestGroup, proposal=self.proposal, operator='SINGLE',
observation_type=RequestGroup.NORMAL)
self.rg_many = mixer.blend(RequestGroup, proposal=self.proposal,
observation_type=RequestGroup.NORMAL)

self.request = mixer.blend(Request, request_group=self.rg_single)
self.requests = mixer.cycle(3).blend(Request, request_group=self.rg_many)
Expand Down
43 changes: 28 additions & 15 deletions observation_portal/requestgroups/test/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,38 +90,44 @@ def setUp(self):

def test_get_request_group_detail_unauthenticated(self):
self.client.force_login(self.other_user)
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup")
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup",
observation_type=RequestGroup.NORMAL)
result = self.client.get(reverse('api:request_groups-detail', args=(request_group.id,)))
self.assertEqual(result.status_code, 404)

def test_get_request_group_detail_authenticated(self):
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup")
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup",
observation_type=RequestGroup.NORMAL)
self.client.force_login(self.user)
result = self.client.get(reverse('api:request_groups-detail', args=(request_group.id,)))
self.assertContains(result, request_group.name)

def test_get_request_group_list_unauthenticated(self):
self.client.force_login(self.other_user)
mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup")
mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup",
observation_type=RequestGroup.NORMAL)
result = self.client.get(reverse('api:request_groups-list'))
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json()['results'], [])

def test_get_request_group_list_authenticated(self):
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup")
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup",
observation_type=RequestGroup.NORMAL)
self.client.force_login(self.user)
result = self.client.get(reverse('api:request_groups-list'))
self.assertContains(result, request_group.name)

def test_get_request_group_list_staff(self):
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup2")
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal, name="testgroup2",
observation_type=RequestGroup.NORMAL)
self.client.force_login(self.staff_user)
result = self.client.get(reverse('api:request_groups-list'))
self.assertContains(result, request_group.name)

def test_get_request_group_detail_public(self):
proposal = mixer.blend(Proposal, public=True)
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=proposal, name="publicgroup")
request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=proposal, name="publicgroup",
observation_type=RequestGroup.NORMAL)
result = self.client.get(reverse('api:request_groups-detail', args=(request_group.id,)))
self.assertContains(result, request_group.name)

Expand Down Expand Up @@ -386,7 +392,7 @@ def setUp(self):
self.user = mixer.blend(User)
self.proposal = mixer.blend(Proposal)
mixer.blend(Membership, proposal=self.proposal, user=self.user)
self.rg = mixer.blend(RequestGroup, proposal=self.proposal)
self.rg = mixer.blend(RequestGroup, proposal=self.proposal, observation_type=RequestGroup.NORMAL)
self.client.force_login(self.user)

def test_cannot_delete_rg(self):
Expand Down Expand Up @@ -1706,7 +1712,8 @@ def setUp(self):
self.user = mixer.blend(User, is_staff=False, is_superuser=False)
self.staff_user = mixer.blend(User, is_staff=True)
mixer.blend(Membership, user=self.user, proposal=self.proposal)
self.request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal)
self.request_group = mixer.blend(RequestGroup, submitter=self.user, proposal=self.proposal,
observation_type=RequestGroup.NORMAL)

def test_get_request_list_authenticated(self):
request = mixer.blend(Request, request_group=self.request_group, observation_note='testobsnote')
Expand Down Expand Up @@ -1910,7 +1917,8 @@ def setUp(self):
self.client.force_login(self.user)

def test_cancel_pending_rg(self, modify_mock):
requestgroup = mixer.blend(RequestGroup, state='PENDING', proposal=self.proposal)
requestgroup = mixer.blend(RequestGroup, state='PENDING', proposal=self.proposal,
observation_type=RequestGroup.NORMAL)
requests = mixer.cycle(3).blend(Request, state='PENDING', request_group=requestgroup)
for request in requests:
mixer.blend(Configuration, request=request, instrument_type='1M0-SCICAM-SBIG')
Expand All @@ -1922,7 +1930,8 @@ def test_cancel_pending_rg(self, modify_mock):
self.assertEqual(Request.objects.get(pk=request.id).state, 'CANCELED')

def test_cancel_pending_rg_some_requests_not_pending(self, modify_mock):
requestgroup = mixer.blend(RequestGroup, state='PENDING', proposal=self.proposal)
requestgroup = mixer.blend(RequestGroup, state='PENDING', proposal=self.proposal,
observation_type=RequestGroup.NORMAL)
pending_r = mixer.blend(Request, state='PENDING', request_group=requestgroup)
mixer.blend(Configuration, request=pending_r, instrument_type='1M0-SCICAM-SBIG')
completed_r = mixer.blend(Request, state='COMPLETED', request_group=requestgroup)
Expand All @@ -1938,7 +1947,8 @@ def test_cancel_pending_rg_some_requests_not_pending(self, modify_mock):
self.assertEqual(Request.objects.get(pk=we_r.id).state, 'WINDOW_EXPIRED')

def test_cannot_cancel_expired_rg(self, modify_mock):
requestgroup = mixer.blend(RequestGroup, state='WINDOW_EXPIRED', proposal=self.proposal)
requestgroup = mixer.blend(RequestGroup, state='WINDOW_EXPIRED', proposal=self.proposal,
observation_type=RequestGroup.NORMAL)
expired_r = mixer.blend(Request, state='WINDOW_EXPIRED', request_group=requestgroup)
response = self.client.post(reverse('api:request_groups-cancel', kwargs={'pk': requestgroup.id}))

Expand All @@ -1947,7 +1957,8 @@ def test_cannot_cancel_expired_rg(self, modify_mock):
self.assertEqual(Request.objects.get(pk=expired_r.id).state, 'WINDOW_EXPIRED')

def test_cannot_cancel_completed_rg(self, modify_mock):
requestgroup = mixer.blend(RequestGroup, state='COMPLETED', proposal=self.proposal)
requestgroup = mixer.blend(RequestGroup, state='COMPLETED', proposal=self.proposal,
observation_type=RequestGroup.NORMAL)
completed_r = mixer.blend(Request, state='COMPLETED', request_group=requestgroup)
expired_r = mixer.blend(Request, state='WINDOW_EXPIRED', request_group=requestgroup)
response = self.client.post(reverse('api:request_groups-cancel', kwargs={'pk': requestgroup.id}))
Expand All @@ -1965,7 +1976,8 @@ def setUp(self):
self.proposal = mixer.blend(Proposal)
mixer.blend(Membership, user=self.user, proposal=self.proposal)
self.client.force_login(self.user)
self.rg = mixer.blend(RequestGroup, operator='MANY', state='PENDING', proposal=self.proposal, modified=timezone.now() - timedelta(weeks=2))
self.rg = mixer.blend(RequestGroup, operator='MANY', state='PENDING', proposal=self.proposal,
modified=timezone.now() - timedelta(weeks=2), observation_type=RequestGroup.NORMAL)
self.requests = mixer.cycle(3).blend(Request, request_group=self.rg, state='PENDING', modified=timezone.now() - timedelta(weeks=2))

## TODO update to remove mocked lake stuff
Expand Down Expand Up @@ -2381,7 +2393,8 @@ def test_anonymize(self):

@patch('observation_portal.requestgroups.contention.get_filtered_rise_set_intervals_by_site')
def test_binned_pressure_by_hours_from_now_should_be_gtzero_pressure(self, mock_intervals):
request = mixer.blend(Request, state='PENDING', duration=120*60) # 2 hour duration.
requestgroup = mixer.blend(RequestGroup, observation_type=RequestGroup.NORMAL)
request = mixer.blend(Request, request_group=requestgroup, state='PENDING', duration=120*60) # 2 hour duration.
mixer.blend(Window, request=request)
mixer.blend(Location, request=request, site='tst')
conf = mixer.blend(Configuration, request=request, instrument_type='1M0-SCICAM-SBIG')
Expand Down Expand Up @@ -2490,7 +2503,7 @@ def test_get_max_ipp_no_ipp_available(self):
class TestFiltering(APITestCase):
def test_filtering_works(self):
proposal = mixer.blend(Proposal, public=True)
mixer.blend(RequestGroup, name='filter on me', proposal=proposal)
mixer.blend(RequestGroup, name='filter on me', proposal=proposal, observation_type=RequestGroup.NORMAL)
response = self.client.get(reverse('api:request_groups-list') + '?name=filter')
self.assertEqual(response.json()['count'], 1)
response = self.client.get(reverse('api:request_groups-list') + '?name=philbobaggins')
Expand Down
6 changes: 4 additions & 2 deletions observation_portal/requestgroups/test/test_cadence.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
from observation_portal.common.test_helpers import SetTimeMixin
from observation_portal.requestgroups.cadence import expand_cadence_request
from observation_portal.requestgroups.models import (
Request, Configuration, Target, Constraints, Location, InstrumentConfig, AcquisitionConfig, GuidingConfig
RequestGroup, Request, Configuration, Target, Constraints, Location, InstrumentConfig, AcquisitionConfig,
GuidingConfig
)


class TestCadence(SetTimeMixin, TestCase):
def setUp(self):
super().setUp()
self.req = mixer.blend(Request)
self.req_group = mixer.blend(RequestGroup, observation_type=RequestGroup.NORMAL)
self.req = mixer.blend(Request, request_group=self.req_group)
self.configuration = mixer.blend(
Configuration, request=self.req, instrument_type='1M0-SCICAM-SBIG', type='EXPOSE'
)
Expand Down
Loading

0 comments on commit eb9acd3

Please sign in to comment.