Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
jchate6 committed Nov 17, 2023
2 parents ff86c3b + 8836b17 commit 0068b2a
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 22 deletions.
4 changes: 3 additions & 1 deletion docs/observing/observation_module.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ from two other classes.
logic” for interacting with the remote observatory. This includes
methods to submit observations, check observation status, etc. It
inherits from ``BaseRoboticObservationFacility``, which contains some
functionality that all observation facility classes will want.
functionality that all observation facility classes will want. You
can access the user within your facility implementation using
``self.user`` if you need it for any api requests.

``MyObservationFacilityForm`` is the class that will display a GUI form
for our users to create an observation. We can submit observations
Expand Down
6 changes: 6 additions & 0 deletions tom_observations/facility.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ class BaseObservationFacility(ABC):
"""
name = 'BaseObservation'

def __init__(self):
self.user = None

def set_user(self, user):
self.user = user

def all_data_products(self, observation_record):
from tom_dataproducts.models import DataProduct
products = {'saved': [], 'unsaved': []}
Expand Down
17 changes: 15 additions & 2 deletions tom_observations/management/commands/updatestatus.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.core.management.base import BaseCommand
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import User

from tom_targets.models import Target
from tom_observations import facility
Expand All @@ -18,19 +19,31 @@ def add_arguments(self, parser):
'--target_id',
help='Update observation statuses for a single target'
)
parser.add_argument(
'--username',
required=False,
help='The username of a user to use if the facility uses per user-based authentication for its API calls'
)

def handle(self, *args, **options):
target = None
user = None
if options['target_id']:
try:
target = Target.objects.get(pk=options['target_id'])
except ObjectDoesNotExist:
raise Exception('Invalid target id provided')
if options.get('username'):
try:
user = User.objects.get(username=options['username'])
except User.DoesNotExist:
raise Exception('Invalid username provided')

failed_records = {}
for facility_name in facility.get_service_classes():
clazz = facility.get_service_class(facility_name)
failed_records[facility_name] = clazz().update_all_observation_statuses(target=target)
instance = facility.get_service_class(facility_name)()
instance.set_user(user)
failed_records[facility_name] = instance.update_all_observation_statuses(target=target)
success = True
for facility_name, errors in failed_records.items():
if len(errors) > 0:
Expand Down
19 changes: 11 additions & 8 deletions tom_observations/templatetags/observation_extras.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,19 @@ def observation_type_tabs(context):
}


@register.inclusion_tag('tom_observations/partials/facility_observation_form.html')
def facility_observation_form(target, facility, observation_type):
@register.inclusion_tag('tom_observations/partials/facility_observation_form.html', takes_context=True)
def facility_observation_form(context, target, facility, observation_type):
"""
Displays a form for submitting an observation for a specific facility and observation type, e.g., imaging.
"""
facility_class = get_service_class(facility)()
facility_instance = get_service_class(facility)()
facility_instance.set_user(context['request'].user)
initial_fields = {
'target_id': target.id,
'facility': facility,
'observation_type': observation_type
}
obs_form = facility_class.get_form(observation_type)(initial=initial_fields)
obs_form = facility_instance.get_form(observation_type)(initial=initial_fields)
obs_form.helper.form_action = reverse('tom_observations:create', kwargs={'facility': facility})

return {'obs_form': obs_form}
Expand Down Expand Up @@ -259,8 +260,8 @@ def observation_distribution(observations):
return {'figure': figure}


@register.inclusion_tag('tom_observations/partials/facility_status.html')
def facility_status():
@register.inclusion_tag('tom_observations/partials/facility_status.html', takes_context=True)
def facility_status(context):
"""
Collect the facility status from the registered facilities and pass them
to the facility_status.html partial template.
Expand All @@ -271,6 +272,7 @@ def facility_status():
facility_statuses = []
for facility_class in get_service_classes().values():
facility = facility_class()
facility.set_user(context['request'].user)
weather_urls = facility.get_facility_weather_urls()
status = facility.get_facility_status()

Expand All @@ -286,11 +288,12 @@ def facility_status():
return {'facilities': facility_statuses}


@register.inclusion_tag('tom_observations/partials/facility_map.html')
def facility_map():
@register.inclusion_tag('tom_observations/partials/facility_map.html', takes_context=True)
def facility_map(context):
facility_locations = []
for facility_class in get_service_classes().values():
facility = facility_class()
facility.set_user(context['request'].user)
sites = facility.get_observing_sites()

# Flatten each facility site dictionary and add text label for use in facility map
Expand Down
19 changes: 19 additions & 0 deletions tom_observations/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,25 @@ def test_submit_observation_robotic(self):
self.assertTrue(ObservationRecord.objects.filter(observation_id='fakeid').exists())
self.assertEqual(ObservationRecord.objects.filter(observation_id='fakeid').first().user, self.user)

@mock.patch('tom_observations.tests.utils.FakeRoboticFacility.set_user')
def test_submit_observation_robotic_gets_user(self, mock_method):
form_data = {
'target_id': self.target.id,
'test_input': 'gnomes',
'facility': 'FakeRoboticFacility',
'observation_type': 'OBSERVATION'
}
self.client.post(
'{}?target_id={}'.format(
reverse('tom_observations:create', kwargs={'facility': 'FakeRoboticFacility'}),
self.target.id
),
data=form_data,
follow=True
)
calls = [mock.call(self.user)]
mock_method.assert_has_calls(calls)

# TODO: this test
# def test_submit_observation_cadence(self):
# form_data = {
Expand Down
32 changes: 21 additions & 11 deletions tom_observations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,9 @@ def get_context_data(self, **kwargs):
context['target'] = target

# allow the Facility class to add data to the context
facility_class = self.get_facility_class()
facility_context = facility_class().get_facility_context_data(target=target)
facility = self.get_facility_class()()
facility.set_user(self.request.user)
facility_context = facility.get_facility_context_data(target=target)
context.update(facility_context)

return context
Expand All @@ -240,8 +241,10 @@ def get_form_class(self):
observation_type = self.request.GET.get('observation_type')
elif self.request.method == 'POST':
observation_type = self.request.POST.get('observation_type')
facility = self.get_facility_class()()
facility.set_user(self.request.user)
form_class = type(f'Composite{observation_type}Form',
(self.get_facility_class()().get_form(observation_type), self.get_cadence_strategy_form()),
(facility.get_form(observation_type), self.get_cadence_strategy_form()),
{})
return form_class

Expand Down Expand Up @@ -309,9 +312,10 @@ def form_valid(self, form):
:type form: subclass of GenericObservationForm
"""
# Submit the observation
facility = self.get_facility_class()
facility = self.get_facility_class()()
facility.set_user(self.request.user)
target = self.get_target()
observation_ids = facility().submit_observation(form.observation_payload())
observation_ids = facility.submit_observation(form.observation_payload())
records = []

for observation_id in observation_ids:
Expand Down Expand Up @@ -377,6 +381,7 @@ def get(self, request, *args, **kwargs):
obsr_id = self.kwargs.get('pk')
obsr = ObservationRecord.objects.get(id=obsr_id)
facility = get_service_class(obsr.facility)()
facility.set_user(request.user)
try:
success = facility.cancel_observation(obsr.observation_id)
if success:
Expand Down Expand Up @@ -500,10 +505,11 @@ def get_context_data(self, *args, **kwargs):
"""
context = super().get_context_data(*args, **kwargs)
context['form'] = AddProductToGroupForm()
service_class = get_service_class(self.object.facility)
context['editable'] = isinstance(service_class(), BaseManualObservationFacility)
context['data_products'] = service_class().all_data_products(self.object)
context['can_be_cancelled'] = self.object.status not in service_class().get_terminal_observing_states()
facility = get_service_class(self.object.facility)()
facility.set_user(self.request.user)
context['editable'] = isinstance(facility, BaseManualObservationFacility)
context['data_products'] = facility.all_data_products(self.object)
context['can_be_cancelled'] = self.object.status not in facility.get_terminal_observing_states()
newest_image = None
for data_product in context['data_products']['saved']:
newest_image = data_product if (not newest_image or data_product.modified > newest_image.modified) and \
Expand Down Expand Up @@ -607,7 +613,9 @@ def get_form_class(self):
raise ValueError('Must provide a facility name')

# TODO: modify this to work with all LCO forms
return get_service_class(facility_name)().get_template_form(None)
facility = get_service_class(facility_name)()
facility.set_user(self.request.user)
return facility.get_template_form(None)

def get_form(self, form_class=None):
form = super().get_form()
Expand Down Expand Up @@ -637,7 +645,9 @@ def get_object(self):

def get_form_class(self):
self.object = self.get_object()
return get_service_class(self.object.facility)().get_template_form(None)
facility = get_service_class(self.object.facility)()
facility.set_user(self.request.user)
return facility.get_template_form(None)

def get_form(self, form_class=None):
form = super().get_form()
Expand Down

0 comments on commit 0068b2a

Please sign in to comment.