From 2b7090de1ccc29a6c0ef6e11f39d20147530b7e3 Mon Sep 17 00:00:00 2001 From: Matthew Li Date: Mon, 13 May 2024 08:56:55 -0700 Subject: [PATCH 1/7] Add AY25-26 periods for BRC/LRC; add UCB 2024-25 calendar periods --- .../commands/data/brc_allocation_periods.json | 45 +++++++++++++++++++ .../commands/data/lrc_allocation_periods.json | 5 +++ 2 files changed, 50 insertions(+) diff --git a/coldfront/core/allocation/management/commands/data/brc_allocation_periods.json b/coldfront/core/allocation/management/commands/data/brc_allocation_periods.json index ad4af549f..0a0d042e5 100644 --- a/coldfront/core/allocation/management/commands/data/brc_allocation_periods.json +++ b/coldfront/core/allocation/management/commands/data/brc_allocation_periods.json @@ -24,6 +24,11 @@ "start_date": "2024-06-01", "end_date": "2025-05-31" }, + { + "name": "Allowance Year 2025 - 2026", + "start_date": "2025-06-01", + "end_date": "2026-05-31" + }, { "name": "Fall Semester 2021", "start_date": "2021-08-18", @@ -143,5 +148,45 @@ "name": "Summer Sessions 2024 - Session F", "start_date": "2024-07-01", "end_date": "2024-07-19" + }, + { + "name": "Fall Semester 2024", + "start_date": "2024-08-21", + "end_date": "2024-12-20" + }, + { + "name": "Spring Semester 2025", + "start_date": "2025-01-14", + "end_date": "2025-05-16" + }, + { + "name": "Summer Sessions 2025 - Session A", + "start_date": "2025-05-27", + "end_date": "2025-07-03" + }, + { + "name": "Summer Sessions 2025 - Session B", + "start_date": "2025-06-09", + "end_date": "2025-08-15" + }, + { + "name": "Summer Sessions 2025 - Session C", + "start_date": "2025-06-23", + "end_date": "2025-08-15" + }, + { + "name": "Summer Sessions 2025 - Session D", + "start_date": "2025-07-07", + "end_date": "2025-08-15" + }, + { + "name": "Summer Sessions 2025 - Session E", + "start_date": "2025-07-28", + "end_date": "2025-08-15" + }, + { + "name": "Summer Sessions 2025 - Session F", + "start_date": "2025-07-07", + "end_date": "2025-07-25" } ] \ No newline at end of file diff --git a/coldfront/core/allocation/management/commands/data/lrc_allocation_periods.json b/coldfront/core/allocation/management/commands/data/lrc_allocation_periods.json index 00c1609b9..7f9d8b034 100644 --- a/coldfront/core/allocation/management/commands/data/lrc_allocation_periods.json +++ b/coldfront/core/allocation/management/commands/data/lrc_allocation_periods.json @@ -18,5 +18,10 @@ "name": "Allowance Year 2024 - 2025", "start_date": "2024-10-01", "end_date": "2025-09-30" + }, + { + "name": "Allowance Year 2025 - 2026", + "start_date": "2025-10-01", + "end_date": "2026-09-30" } ] \ No newline at end of file From 6baa02c95d074be6a26fac64738342dc11c035c5 Mon Sep 17 00:00:00 2001 From: Rae Xin Date: Mon, 13 May 2024 22:30:49 -0700 Subject: [PATCH 2/7] Working TestRenewalSurveyResponses tests --- .../core/utils/tests/test_export_data.py | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) diff --git a/coldfront/core/utils/tests/test_export_data.py b/coldfront/core/utils/tests/test_export_data.py index 0e74dd72c..f60f94b46 100644 --- a/coldfront/core/utils/tests/test_export_data.py +++ b/coldfront/core/utils/tests/test_export_data.py @@ -8,6 +8,8 @@ from django.contrib.auth.models import User from django.core.management import call_command, CommandError +from django.urls import reverse +from http import HTTPStatus from coldfront.api.statistics.utils import get_accounting_allocation_objects, \ create_project_allocation, create_user_project_allocation @@ -19,10 +21,13 @@ from coldfront.core.utils.common import utc_now_offset_aware from coldfront.core.utils.tests.test_base import enable_deployment from coldfront.core.utils.tests.test_base import TestBase +from coldfront.core.allocation.models import AllocationRenewalRequest, AllocationPeriod, \ + AllocationRenewalRequestStatusChoice from coldfront.core.project.models import Project, ProjectStatusChoice, \ ProjectUser, ProjectUserStatusChoice, ProjectUserRoleChoice, \ ProjectAllocationRequestStatusChoice, SavioProjectAllocationRequest, \ VectorProjectAllocationRequest +from coldfront.core.project.utils_.renewal_utils import get_current_allowance_year_period from coldfront.core.resource.models import Resource from coldfront.core.resource.utils_.allowance_utils.constants import BRCAllowances from coldfront.core.resource.utils_.allowance_utils.interface import ComputingAllowanceInterface @@ -999,3 +1004,207 @@ def test_get_new_project_survey_responses_allowance_type(self): err.seek(0) self.assertEqual(err.read(), '') + +class TestRenewalSurveyResponses(TestBase): + """ Test class to test export data subcommand renewal_survey_responses runs correctly """ + + @enable_deployment('BRC') + def setUp(self): + super().setUp() + + allocation_period = AllocationPeriod.objects.get(name__exact='Allowance Year 2024 - 2025') + + renewal_survey = { + "brc_feedback": "N/A", + "mybrc_comments": "", + "do_you_use_mybrc": "no", + "classes_being_taught": "N/A", + "colleague_suggestions": "N/A", + "grants_supported_by_brc": "Grant #1 etc. etc.\r\nGrant #2 etc. etc.", + "which_brc_services_used": ["savio_hpc", "srdc"], + "indicate_topic_interests": ["have_visited_rdmp_website", + "have_had_rdmp_event_or_consultation", + "want_to_learn_security_and_have_rdm_consult"], + "brc_recommendation_rating": "6", + "publications_supported_by_brc": "N/A", + "which_open_ondemand_apps_used": ["desktop", "matlab", + "jupyter_notebook", "vscode_server"], + "recruitment_or_retention_cases": "N/A", + "brc_recommendation_rating_reason": "Easy to use", + "how_important_to_research_is_brc": "5", + "training_session_other_topics_of_interest": "None", + "how_brc_helped_bootstrap_computational_methods": "N/A", + "training_session_usefulness_of_basic_savio_cluster": "4", + "training_session_usefulness_of_singularity_on_savio": "4", + "training_session_usefulness_of_advanced_savio_cluster": "2", + "training_session_usefulness_of_analytic_envs_on_demand": "5", + "training_session_usefulness_of_computational_platforms_training": "3"} + + project_name = 'fc_project' + active_project_status = ProjectStatusChoice.objects.get(name='Active') + project = Project.objects.create( + name=project_name, + title=project_name, + status=active_project_status) + requester = User.objects.create( + email='requester@email.com', + first_name='Requester', + last_name='User', + username='requester') + pi = User.objects.create( + email='pi@email.com', + first_name='PI', + last_name='User', + username='pi') + allocation_period_start_utc = display_time_zone_date_to_utc_datetime( + allocation_period.start_date) + request = AllocationRenewalRequest.objects.create( + requester=requester, + pi=pi, + computing_allowance=Resource.objects.get( + name=BRCAllowances.FCA), + allocation_period=allocation_period, + status=AllocationRenewalRequestStatusChoice.objects.get( + name='Under Review'), + renewal_survey_answers = renewal_survey, + pre_project=project, + post_project=project, + request_time=allocation_period_start_utc - datetime.timedelta(days=1)) + self.project_name = project_name + self.expected_survey_answers = { + '1. Which Berkeley Research Computing services have you used? (Check all that apply.)': [ + 'Savio High Performance Computing and consulting', + 'Secure Research Data & Computing (SRDC)' + ], + "2. Please list any publications (including papers, books, dissertations, theses, and " + "public presentations) that you authored or co-authored, that have been supported by " + "Berkeley Research Computing resources and/or consulting. Please provide a bibliographic " + "reference, URL or DOI for each publication/presentation. Please write 'N/A' if this " + "does not apply.": 'N/A', + "3. Please list any grant(s) or other competitively-awarded funding that has been or will " + "be supported by Berkeley Research Computing resources and/or consulting. Please provide " + "the name of the funding agency, the award number or other identifier, and the amount of " + "funding awarded. Please write 'N/A' if this does not apply.": 'Grant #1 etc. etc.\r\n' + 'Grant #2 etc. etc.', + "4. Please list any recruitment or retention cases you are aware of in which the " + "availability of the Savio high-performance computing cluster or other Berkeley Research " + "Computing services -- such as Condo Storage, Analytic Environments on Demand (AEoD), or " + "Cloud Computing Support -- played a role? Please indicate the recruitment / retention " + "case role (faculty, postdoc, or graduate student), department, sponsoring faculty member, " + "and outcome. This information will not be shared publicly, except as a component of " + "aggregated statistics. Please write 'N/A' if this does not apply.": 'N/A', + '5. Please list any classes (course number and semester) for which you were/will be an ' + 'instructor, and that were or will be supported by the Berkeley Research Computing Program.' + ' Please indicate whether an Instructional Computing Allowance (ICA) was, is, or will be an' + ' element of support for the listed classes. More on ICAs ' + 'here' + '. Please write \'N/A\' if this does not apply.': 'N/A', + '6. Based upon your overall experience using BRC services, how likely are you to recommend ' + 'Berkeley Research Computing to others?': '6', + '6a. What is the reason for your rating above?': 'Easy to use', + "7. If you are new to computational methods (broadly, or in a specific application), please" + " let us know how BRC services and/or resources have helped you bootstrap the application " + "of computational methods to your research. Please write 'N/A' if this does not apply.": + 'N/A', + '8. How important is the Berkeley Research Computing Program to your research?': 'Essential', + '9. Do you use the Savio Account Management portal MyBRC?': 'No', + '9a.If yes, what feedback do you have for MyBRC?': '', + '10. Do you use Open Ondemand? Which application(s) do you use? (Check all that apply.)': [ + 'Desktop', + 'MatLab', + 'Jupyter Notebook/Lab', + 'VS Code Server' + ], + '11. How could the Berkeley Research Computing Program be more useful to your research or ' + 'teaching?': 'N/A', + '12. Please suggest colleagues who might benefit from the Berkeley Research Computing ' + 'Program, with whom we should follow up. Names, e-mail addresses, and roles (faculty, ' + 'postdoc, graduate student, etc.) would be most helpful.': 'N/A', + '13. Please indicate your engagement with or interest in the following topics. (Check all ' + 'that apply.)': [ + 'I have visited the Research Data Management Program web site.', + 'I have participated in a Research Data ' + 'Management Program event or consultation.', + 'I am interested in learning more about securing research data and/or secure ' + 'computation; please have an RDM consultant follow up with me.' + ], + '

BRC is planning an in-person training session within the next 2-3 months and would ' + 'like input on what topics would be most useful to you personally. Please rate the ' + 'following topics on how useful they would be to you.

14a. Selecting computational ' + 'platforms that fit your research and budget (Savio, HPC@UC, XSEDE, commercial cloud ' + 'providers, AEoD) System overview (how to access Savio via condo contribution or faculty ' + 'compute allowance, system capabilities)': '3', + '14b. Basic usage of the Savio cluster (logging on, data transfer, accessing software, ' + 'using the scheduler; limited discussion of access models and capabilities)': '4', + '14c. Advanced usage of the Savio cluster (e.g. installing your own software, ' + 'parallelization strategies, effective use of specific system resources such as GPUs and ' + 'Hadoop/Spark -- please indicate specific interests below)': '2', + '14d. Use of Singularity on Savio (containerized applications, including Docker containers ' + 'packaged for Savio deployment)': '4', + '14e. Use of Analytic Environments on Demand (virtualized, scalable Windows environments ' + 'provisioned with licensed or open-source software applications applicable to research ' + 'projects)': '5 - Very useful', + '15. Any other or specific topics of interest?': 'None' + } + + @enable_deployment('BRC') + def test_get_renewal_survey_responses_json(self): + out, err = StringIO(''), StringIO('') + call_command('export_data', 'renewal_survey_responses', + '--format=json', '--allocation_period=Allowance Year 2024 - 2025', + stdout=out, stderr=err) + sys.stdout = sys.__stdout__ + + out.seek(0) + output = json.loads(''.join(out.readlines())) + for item in output: + project_name = item.pop('project_name') + self.assertEquals(project_name, self.project_name) + self.assertDictEqual(item['renewal_survey_responses'], self.expected_survey_answers) + err.seek(0) + self.assertEqual(err.read(), '') + + @enable_deployment('BRC') + def test_get_renewal_survey_responses_csv(self): + out, err = StringIO(''), StringIO('') + call_command('export_data', 'renewal_survey_responses', + '--format=csv', '--allocation_period=Allowance Year 2024 - 2025', + stdout=out, stderr=err) + sys.stdout = sys.__stdout__ + + out.seek(0) + reader = DictReader(out.readlines()) + for item in reader: + project_name = item.pop('project_name') + item.pop('project_title') + item.pop('project_pi') + self.assertEquals(project_name, self.project_name) + self.assertEqual(len(item), len(self.expected_survey_answers)) + sample = "8. How important is the Berkeley Research Computing Program to your research?" + self.assertEqual(item[sample], self.expected_survey_answers[sample]) + + err.seek(0) + self.assertEqual(err.read(), '') + + @enable_deployment('BRC') + def test_get_renewal_survey_responses_allowance_type(self): + out, err = StringIO(''), StringIO('') + call_command('export_data', 'renewal_survey_responses', + '--format=csv', '--allocation_period=Allowance Year 2024 - 2025', + '--allowance_type=fc_', stdout=out, stderr=err) + sys.stdout = sys.__stdout__ + + out.seek(0) + reader = DictReader(out.readlines()) + for item in reader: + project_name = item.pop('project_name') + item.pop('project_title') + item.pop('project_pi') + self.assertEquals(project_name, self.project_name) + self.assertEqual(len(item), len(self.expected_survey_answers)) + sample = "8. How important is the Berkeley Research Computing Program to your research?" + self.assertEqual(item[sample], self.expected_survey_answers[sample]) + + err.seek(0) + self.assertEqual(err.read(), '') \ No newline at end of file From d688a97eac2875b78012eb9cc454b78ecf355010 Mon Sep 17 00:00:00 2001 From: Rae Xin Date: Thu, 16 May 2024 11:19:37 -0700 Subject: [PATCH 3/7] Adding multiple AllocationRenewalRequest objects to 'export_data' testing, test works for json test so far --- .../core/utils/tests/test_export_data.py | 287 +++++++++--------- 1 file changed, 139 insertions(+), 148 deletions(-) diff --git a/coldfront/core/utils/tests/test_export_data.py b/coldfront/core/utils/tests/test_export_data.py index f60f94b46..0c866fec8 100644 --- a/coldfront/core/utils/tests/test_export_data.py +++ b/coldfront/core/utils/tests/test_export_data.py @@ -9,6 +9,7 @@ from django.contrib.auth.models import User from django.core.management import call_command, CommandError from django.urls import reverse +from django import forms from http import HTTPStatus from coldfront.api.statistics.utils import get_accounting_allocation_objects, \ @@ -27,6 +28,7 @@ ProjectUser, ProjectUserStatusChoice, ProjectUserRoleChoice, \ ProjectAllocationRequestStatusChoice, SavioProjectAllocationRequest, \ VectorProjectAllocationRequest +from coldfront.core.project.forms_.renewal_forms.request_forms import ProjectRenewalSurveyForm from coldfront.core.project.utils_.renewal_utils import get_current_allowance_year_period from coldfront.core.resource.models import Resource from coldfront.core.resource.utils_.allowance_utils.constants import BRCAllowances @@ -1007,146 +1009,86 @@ def test_get_new_project_survey_responses_allowance_type(self): class TestRenewalSurveyResponses(TestBase): """ Test class to test export data subcommand renewal_survey_responses runs correctly """ - + @enable_deployment('BRC') def setUp(self): super().setUp() - allocation_period = AllocationPeriod.objects.get(name__exact='Allowance Year 2024 - 2025') + fixtures = [] + filtered_fixtures = [] - renewal_survey = { - "brc_feedback": "N/A", - "mybrc_comments": "", - "do_you_use_mybrc": "no", - "classes_being_taught": "N/A", - "colleague_suggestions": "N/A", - "grants_supported_by_brc": "Grant #1 etc. etc.\r\nGrant #2 etc. etc.", - "which_brc_services_used": ["savio_hpc", "srdc"], - "indicate_topic_interests": ["have_visited_rdmp_website", - "have_had_rdmp_event_or_consultation", - "want_to_learn_security_and_have_rdm_consult"], - "brc_recommendation_rating": "6", - "publications_supported_by_brc": "N/A", - "which_open_ondemand_apps_used": ["desktop", "matlab", - "jupyter_notebook", "vscode_server"], - "recruitment_or_retention_cases": "N/A", - "brc_recommendation_rating_reason": "Easy to use", - "how_important_to_research_is_brc": "5", - "training_session_other_topics_of_interest": "None", - "how_brc_helped_bootstrap_computational_methods": "N/A", - "training_session_usefulness_of_basic_savio_cluster": "4", - "training_session_usefulness_of_singularity_on_savio": "4", - "training_session_usefulness_of_advanced_savio_cluster": "2", - "training_session_usefulness_of_analytic_envs_on_demand": "5", - "training_session_usefulness_of_computational_platforms_training": "3"} + allocation_period = AllocationPeriod.objects.get(name__exact='Allowance Year 2024 - 2025') - project_name = 'fc_project' - active_project_status = ProjectStatusChoice.objects.get(name='Active') - project = Project.objects.create( - name=project_name, - title=project_name, - status=active_project_status) - requester = User.objects.create( - email='requester@email.com', - first_name='Requester', - last_name='User', - username='requester') - pi = User.objects.create( - email='pi@email.com', - first_name='PI', - last_name='User', - username='pi') - allocation_period_start_utc = display_time_zone_date_to_utc_datetime( - allocation_period.start_date) - request = AllocationRenewalRequest.objects.create( - requester=requester, - pi=pi, - computing_allowance=Resource.objects.get( - name=BRCAllowances.FCA), - allocation_period=allocation_period, - status=AllocationRenewalRequestStatusChoice.objects.get( - name='Under Review'), - renewal_survey_answers = renewal_survey, - pre_project=project, - post_project=project, - request_time=allocation_period_start_utc - datetime.timedelta(days=1)) - self.project_name = project_name - self.expected_survey_answers = { - '1. Which Berkeley Research Computing services have you used? (Check all that apply.)': [ - 'Savio High Performance Computing and consulting', - 'Secure Research Data & Computing (SRDC)' - ], - "2. Please list any publications (including papers, books, dissertations, theses, and " - "public presentations) that you authored or co-authored, that have been supported by " - "Berkeley Research Computing resources and/or consulting. Please provide a bibliographic " - "reference, URL or DOI for each publication/presentation. Please write 'N/A' if this " - "does not apply.": 'N/A', - "3. Please list any grant(s) or other competitively-awarded funding that has been or will " - "be supported by Berkeley Research Computing resources and/or consulting. Please provide " - "the name of the funding agency, the award number or other identifier, and the amount of " - "funding awarded. Please write 'N/A' if this does not apply.": 'Grant #1 etc. etc.\r\n' - 'Grant #2 etc. etc.', - "4. Please list any recruitment or retention cases you are aware of in which the " - "availability of the Savio high-performance computing cluster or other Berkeley Research " - "Computing services -- such as Condo Storage, Analytic Environments on Demand (AEoD), or " - "Cloud Computing Support -- played a role? Please indicate the recruitment / retention " - "case role (faculty, postdoc, or graduate student), department, sponsoring faculty member, " - "and outcome. This information will not be shared publicly, except as a component of " - "aggregated statistics. Please write 'N/A' if this does not apply.": 'N/A', - '5. Please list any classes (course number and semester) for which you were/will be an ' - 'instructor, and that were or will be supported by the Berkeley Research Computing Program.' - ' Please indicate whether an Instructional Computing Allowance (ICA) was, is, or will be an' - ' element of support for the listed classes. More on ICAs ' - 'here' - '. Please write \'N/A\' if this does not apply.': 'N/A', - '6. Based upon your overall experience using BRC services, how likely are you to recommend ' - 'Berkeley Research Computing to others?': '6', - '6a. What is the reason for your rating above?': 'Easy to use', - "7. If you are new to computational methods (broadly, or in a specific application), please" - " let us know how BRC services and/or resources have helped you bootstrap the application " - "of computational methods to your research. Please write 'N/A' if this does not apply.": - 'N/A', - '8. How important is the Berkeley Research Computing Program to your research?': 'Essential', - '9. Do you use the Savio Account Management portal MyBRC?': 'No', - '9a.If yes, what feedback do you have for MyBRC?': '', - '10. Do you use Open Ondemand? Which application(s) do you use? (Check all that apply.)': [ - 'Desktop', - 'MatLab', - 'Jupyter Notebook/Lab', - 'VS Code Server' - ], - '11. How could the Berkeley Research Computing Program be more useful to your research or ' - 'teaching?': 'N/A', - '12. Please suggest colleagues who might benefit from the Berkeley Research Computing ' - 'Program, with whom we should follow up. Names, e-mail addresses, and roles (faculty, ' - 'postdoc, graduate student, etc.) would be most helpful.': 'N/A', - '13. Please indicate your engagement with or interest in the following topics. (Check all ' - 'that apply.)': [ - 'I have visited the Research Data Management Program web site.', - 'I have participated in a Research Data ' - 'Management Program event or consultation.', - 'I am interested in learning more about securing research data and/or secure ' - 'computation; please have an RDM consultant follow up with me.' - ], - '

BRC is planning an in-person training session within the next 2-3 months and would ' - 'like input on what topics would be most useful to you personally. Please rate the ' - 'following topics on how useful they would be to you.

14a. Selecting computational ' - 'platforms that fit your research and budget (Savio, HPC@UC, XSEDE, commercial cloud ' - 'providers, AEoD) System overview (how to access Savio via condo contribution or faculty ' - 'compute allowance, system capabilities)': '3', - '14b. Basic usage of the Savio cluster (logging on, data transfer, accessing software, ' - 'using the scheduler; limited discussion of access models and capabilities)': '4', - '14c. Advanced usage of the Savio cluster (e.g. installing your own software, ' - 'parallelization strategies, effective use of specific system resources such as GPUs and ' - 'Hadoop/Spark -- please indicate specific interests below)': '2', - '14d. Use of Singularity on Savio (containerized applications, including Docker containers ' - 'packaged for Savio deployment)': '4', - '14e. Use of Analytic Environments on Demand (virtualized, scalable Windows environments ' - 'provisioned with licensed or open-source software applications applicable to research ' - 'projects)': '5 - Very useful', - '15. Any other or specific topics of interest?': 'None' - } + for index in range(5): + pi = User.objects.create( + username=f'test_user{index}', first_name='Test', last_name='User', + is_superuser=True) + + renewal_survey = { + "brc_feedback": "N/A", + "mybrc_comments": "", + "do_you_use_mybrc": "no", + "classes_being_taught": f"sample answer {index}", + "colleague_suggestions": "N/A", + "grants_supported_by_brc": "Grant #1 etc. etc.\r\nGrant #2 etc. etc.", + "which_brc_services_used": ["savio_hpc", "srdc"], + "indicate_topic_interests": ["have_visited_rdmp_website", + "have_had_rdmp_event_or_consultation", + "want_to_learn_security_and_have_rdm_consult"], + "brc_recommendation_rating": "6", + "publications_supported_by_brc": "N/A", + "which_open_ondemand_apps_used": ["desktop", "matlab", + "jupyter_notebook", "vscode_server"], + "recruitment_or_retention_cases": "N/A", + "brc_recommendation_rating_reason": "Easy to use", + "how_important_to_research_is_brc": "5", + "training_session_other_topics_of_interest": "None", + "how_brc_helped_bootstrap_computational_methods": "N/A", + "training_session_usefulness_of_basic_savio_cluster": "4", + "training_session_usefulness_of_singularity_on_savio": "4", + "training_session_usefulness_of_advanced_savio_cluster": "2", + "training_session_usefulness_of_analytic_envs_on_demand": "5", + "training_session_usefulness_of_computational_platforms_training": "3"} + + active_project_status = ProjectStatusChoice.objects.get(name='Active') + + project_prefix = 'fc_' if index % 2 else 'pc_' + project = Project.objects.create(name=f'{project_prefix}test_project{index}', + status=active_project_status) + + requester = User.objects.create( + email=f'requester{index}@email.com', + first_name='Requester', + last_name=f'User {index}', + username=f'requester{index}') + pi = User.objects.create( + email=f'pi{index}@email.com', + first_name='PI', + last_name=f'User {index}', + username=f'pi{index}') + allocation_period_start_utc = display_time_zone_date_to_utc_datetime( + allocation_period.start_date) + fixture = AllocationRenewalRequest.objects.create( + requester=requester, + pi=pi, + computing_allowance=Resource.objects.get( + name=BRCAllowances.FCA), + allocation_period=allocation_period, + status=AllocationRenewalRequestStatusChoice.objects.get( + name='Under Review'), + renewal_survey_answers = renewal_survey, + pre_project=project, + post_project=project, + request_time=allocation_period_start_utc - datetime.timedelta(days=1)) + + fixtures.append(fixture) + if index % 2: + filtered_fixtures.append(fixture) + + fixtures = list(sorted(fixtures, key=lambda x: x.pre_project.name, reverse=True)) + filtered_fixtures = list(sorted(filtered_fixtures, key=lambda x: x.pre_project.name, reverse=True)) + self.fixtures = fixtures + self.filtered_fixtures = filtered_fixtures @enable_deployment('BRC') def test_get_renewal_survey_responses_json(self): @@ -1158,10 +1100,16 @@ def test_get_renewal_survey_responses_json(self): out.seek(0) output = json.loads(''.join(out.readlines())) - for item in output: + # print("output:") + # print(output) + # print("fixtures:") + # print(self.fixtures) + for index, item in enumerate(output): project_name = item.pop('project_name') - self.assertEquals(project_name, self.project_name) - self.assertDictEqual(item['renewal_survey_responses'], self.expected_survey_answers) + self.assertEquals(project_name, self.fixtures[index].pre_project.name) + # print("renewal answers for index #" + str(index)) + # print(self.fixtures[index].renewal_survey_answers) + self.assertDictEqual(item['renewal_survey_responses'], swap_form_answer_id_for_text(self.fixtures[index].renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') @@ -1175,14 +1123,15 @@ def test_get_renewal_survey_responses_csv(self): out.seek(0) reader = DictReader(out.readlines()) - for item in reader: + for index, item in enumerate(reader): project_name = item.pop('project_name') item.pop('project_title') item.pop('project_pi') - self.assertEquals(project_name, self.project_name) - self.assertEqual(len(item), len(self.expected_survey_answers)) - sample = "8. How important is the Berkeley Research Computing Program to your research?" - self.assertEqual(item[sample], self.expected_survey_answers[sample]) + self.assertEquals(project_name, self.fixtures[index].pre_project.name) + self.assertEqual(len(item), len(self.fixtures[index].renewal_survey_answers)) + sample = ("6. Based upon your overall experience using BRC services, how likely are you" + " to recommend Berkeley Research Computing to others?") + self.assertEqual(item[sample], self.fixtures[index].renewal_survey_answers[sample]) err.seek(0) self.assertEqual(err.read(), '') @@ -1197,14 +1146,56 @@ def test_get_renewal_survey_responses_allowance_type(self): out.seek(0) reader = DictReader(out.readlines()) - for item in reader: + # print("reader:") + # print(reader) + # print("fixtures:") + # print(self.fixtures) + for index, item in enumerate(reader): project_name = item.pop('project_name') item.pop('project_title') + # print("project name: " + project_name) item.pop('project_pi') - self.assertEquals(project_name, self.project_name) - self.assertEqual(len(item), len(self.expected_survey_answers)) - sample = "8. How important is the Berkeley Research Computing Program to your research?" - self.assertEqual(item[sample], self.expected_survey_answers[sample]) + self.assertEquals(project_name, self.filtered_fixtures[index].pre_project.name) + self.assertEqual(len(item), len(self.filtered_fixtures[index].renewal_survey_answers)) + sample = ("6. Based upon your overall experience using BRC services, how likely are you" + " to recommend Berkeley Research Computing to others?") + self.assertEqual(item[sample], self.fixtures[index].renewal_survey_answers[sample]) err.seek(0) - self.assertEqual(err.read(), '') \ No newline at end of file + self.assertEqual(err.read(), '') + +@staticmethod +def swap_form_answer_id_for_text(survey): + multiple_choice_fields = {} + form = ProjectRenewalSurveyForm() + for k, v in form.fields.items(): + # Only ChoiceField or MultipleChoiceField (in this specific survey form) have choices + if (isinstance(v, forms.MultipleChoiceField)) or (isinstance(v, forms.ChoiceField)): + multiple_choice_fields[k] = {_k: _v for _k, _v in form.fields[k].choices} + for question, answer in survey.items(): + if question in multiple_choice_fields.keys(): + sub_map = multiple_choice_fields[question] + if (isinstance(answer, list)): + # Multiple choice, array + survey[question] = [sub_map.get(i,i) for i in answer] + elif answer != "": + # Single choice replacement + survey[question] = sub_map[answer] + # Change keys of survey (question IDs) to be the human-readable text + # print("form.fields.items():") + # print(form.fields.items()) + # print("starting survey:") + # print(survey) + for id, text in form.fields.items(): + # print("survey[text.label]:") + # print(survey[text.label]) + # print("id:") + # print(id) + # print("text:") + # print(text) + # print("survey.pop(id):") + # print(survey[id]) + survey[text.label] = survey.pop(id) + # print("after assignment, survey[text.label]:") + # print(survey[text.label]) + return survey \ No newline at end of file From 5a61c1596a4ff9acf8ee3e9f3f3a31c43b884d1a Mon Sep 17 00:00:00 2001 From: Rae Xin Date: Thu, 16 May 2024 11:34:04 -0700 Subject: [PATCH 4/7] Tests for export_data.TestRenewalSurveyResponses work and pass. CSV test is a little scuffed, haven't gotten the formatting 100% down so right now it just checks survey length and checks against a specific survey entry. --- .../core/utils/tests/test_export_data.py | 61 +++++++------------ 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/coldfront/core/utils/tests/test_export_data.py b/coldfront/core/utils/tests/test_export_data.py index 0c866fec8..414988488 100644 --- a/coldfront/core/utils/tests/test_export_data.py +++ b/coldfront/core/utils/tests/test_export_data.py @@ -1100,16 +1100,11 @@ def test_get_renewal_survey_responses_json(self): out.seek(0) output = json.loads(''.join(out.readlines())) - # print("output:") - # print(output) - # print("fixtures:") - # print(self.fixtures) for index, item in enumerate(output): project_name = item.pop('project_name') - self.assertEquals(project_name, self.fixtures[index].pre_project.name) - # print("renewal answers for index #" + str(index)) - # print(self.fixtures[index].renewal_survey_answers) - self.assertDictEqual(item['renewal_survey_responses'], swap_form_answer_id_for_text(self.fixtures[index].renewal_survey_answers)) + self.assertEqual(project_name, self.fixtures[index].pre_project.name) + self.assertEqual(item['renewal_survey_responses'], + swap_form_answer_id_for_text(self.fixtures[index].renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') @@ -1127,11 +1122,12 @@ def test_get_renewal_survey_responses_csv(self): project_name = item.pop('project_name') item.pop('project_title') item.pop('project_pi') - self.assertEquals(project_name, self.fixtures[index].pre_project.name) + self.assertEqual(project_name, self.fixtures[index].pre_project.name) self.assertEqual(len(item), len(self.fixtures[index].renewal_survey_answers)) sample = ("6. Based upon your overall experience using BRC services, how likely are you" " to recommend Berkeley Research Computing to others?") - self.assertEqual(item[sample], self.fixtures[index].renewal_survey_answers[sample]) + sample_answer = "6" + self.assertEqual(item[sample], sample_answer) err.seek(0) self.assertEqual(err.read(), '') @@ -1140,32 +1136,33 @@ def test_get_renewal_survey_responses_csv(self): def test_get_renewal_survey_responses_allowance_type(self): out, err = StringIO(''), StringIO('') call_command('export_data', 'renewal_survey_responses', - '--format=csv', '--allocation_period=Allowance Year 2024 - 2025', + '--format=json', '--allocation_period=Allowance Year 2024 - 2025', '--allowance_type=fc_', stdout=out, stderr=err) sys.stdout = sys.__stdout__ out.seek(0) - reader = DictReader(out.readlines()) - # print("reader:") - # print(reader) - # print("fixtures:") - # print(self.fixtures) - for index, item in enumerate(reader): + output = json.loads(''.join(out.readlines())) + for index, item in enumerate(output): project_name = item.pop('project_name') - item.pop('project_title') - # print("project name: " + project_name) - item.pop('project_pi') - self.assertEquals(project_name, self.filtered_fixtures[index].pre_project.name) - self.assertEqual(len(item), len(self.filtered_fixtures[index].renewal_survey_answers)) - sample = ("6. Based upon your overall experience using BRC services, how likely are you" - " to recommend Berkeley Research Computing to others?") - self.assertEqual(item[sample], self.fixtures[index].renewal_survey_answers[sample]) + self.assertEqual(project_name, self.filtered_fixtures[index].pre_project.name) + self.assertEqual(item['renewal_survey_responses'], + swap_form_answer_id_for_text(self.filtered_fixtures[index].renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') @staticmethod def swap_form_answer_id_for_text(survey): + ''' + Takes a survey, a dict mapping survey question IDs to answer IDs. + Uses ProjectRenewalSurveyForm. + Swaps answer IDs for answer text, then question IDs for question text. + Returns the modified survey. + + Parameter + ---------- + _survey : survey to modify + ''' multiple_choice_fields = {} form = ProjectRenewalSurveyForm() for k, v in form.fields.items(): @@ -1182,20 +1179,6 @@ def swap_form_answer_id_for_text(survey): # Single choice replacement survey[question] = sub_map[answer] # Change keys of survey (question IDs) to be the human-readable text - # print("form.fields.items():") - # print(form.fields.items()) - # print("starting survey:") - # print(survey) for id, text in form.fields.items(): - # print("survey[text.label]:") - # print(survey[text.label]) - # print("id:") - # print(id) - # print("text:") - # print(text) - # print("survey.pop(id):") - # print(survey[id]) survey[text.label] = survey.pop(id) - # print("after assignment, survey[text.label]:") - # print(survey[text.label]) return survey \ No newline at end of file From 6ac7bcd0768e3c6d2907db88e79e263ffac718ba Mon Sep 17 00:00:00 2001 From: Rae Xin Date: Thu, 16 May 2024 18:31:29 -0700 Subject: [PATCH 5/7] Moved method to be used as static method --- .../core/utils/tests/test_export_data.py | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/coldfront/core/utils/tests/test_export_data.py b/coldfront/core/utils/tests/test_export_data.py index 414988488..15066ecd1 100644 --- a/coldfront/core/utils/tests/test_export_data.py +++ b/coldfront/core/utils/tests/test_export_data.py @@ -1104,7 +1104,7 @@ def test_get_renewal_survey_responses_json(self): project_name = item.pop('project_name') self.assertEqual(project_name, self.fixtures[index].pre_project.name) self.assertEqual(item['renewal_survey_responses'], - swap_form_answer_id_for_text(self.fixtures[index].renewal_survey_answers)) + self.swap_form_answer_id_for_text(self.fixtures[index].renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') @@ -1146,39 +1146,39 @@ def test_get_renewal_survey_responses_allowance_type(self): project_name = item.pop('project_name') self.assertEqual(project_name, self.filtered_fixtures[index].pre_project.name) self.assertEqual(item['renewal_survey_responses'], - swap_form_answer_id_for_text(self.filtered_fixtures[index].renewal_survey_answers)) + self.swap_form_answer_id_for_text(self.filtered_fixtures[index].renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') -@staticmethod -def swap_form_answer_id_for_text(survey): - ''' - Takes a survey, a dict mapping survey question IDs to answer IDs. - Uses ProjectRenewalSurveyForm. - Swaps answer IDs for answer text, then question IDs for question text. - Returns the modified survey. - - Parameter - ---------- - _survey : survey to modify - ''' - multiple_choice_fields = {} - form = ProjectRenewalSurveyForm() - for k, v in form.fields.items(): - # Only ChoiceField or MultipleChoiceField (in this specific survey form) have choices - if (isinstance(v, forms.MultipleChoiceField)) or (isinstance(v, forms.ChoiceField)): - multiple_choice_fields[k] = {_k: _v for _k, _v in form.fields[k].choices} - for question, answer in survey.items(): - if question in multiple_choice_fields.keys(): - sub_map = multiple_choice_fields[question] - if (isinstance(answer, list)): - # Multiple choice, array - survey[question] = [sub_map.get(i,i) for i in answer] - elif answer != "": - # Single choice replacement - survey[question] = sub_map[answer] - # Change keys of survey (question IDs) to be the human-readable text - for id, text in form.fields.items(): - survey[text.label] = survey.pop(id) - return survey \ No newline at end of file + @staticmethod + def swap_form_answer_id_for_text(survey): + ''' + Takes a survey, a dict mapping survey question IDs to answer IDs. + Uses ProjectRenewalSurveyForm. + Swaps answer IDs for answer text, then question IDs for question text. + Returns the modified survey. + + Parameter + ---------- + _survey : survey to modify + ''' + multiple_choice_fields = {} + form = ProjectRenewalSurveyForm() + for k, v in form.fields.items(): + # Only ChoiceField or MultipleChoiceField (in this specific survey form) have choices + if (isinstance(v, forms.MultipleChoiceField)) or (isinstance(v, forms.ChoiceField)): + multiple_choice_fields[k] = {_k: _v for _k, _v in form.fields[k].choices} + for question, answer in survey.items(): + if question in multiple_choice_fields.keys(): + sub_map = multiple_choice_fields[question] + if (isinstance(answer, list)): + # Multiple choice, array + survey[question] = [sub_map.get(i,i) for i in answer] + elif answer != "": + # Single choice replacement + survey[question] = sub_map[answer] + # Change keys of survey (question IDs) to be the human-readable text + for id, text in form.fields.items(): + survey[text.label] = survey.pop(id) + return survey \ No newline at end of file From fe6fe0c2b1b4640a51361edcadcb5c955ef179ae Mon Sep 17 00:00:00 2001 From: Rae Xin Date: Thu, 16 May 2024 19:11:21 -0700 Subject: [PATCH 6/7] Fixed some small details, added asserts for project_name and pi for the CSV test --- coldfront/core/utils/tests/test_export_data.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/coldfront/core/utils/tests/test_export_data.py b/coldfront/core/utils/tests/test_export_data.py index 15066ecd1..2d5e0d2a1 100644 --- a/coldfront/core/utils/tests/test_export_data.py +++ b/coldfront/core/utils/tests/test_export_data.py @@ -15,15 +15,14 @@ from coldfront.api.statistics.utils import get_accounting_allocation_objects, \ create_project_allocation, create_user_project_allocation from coldfront.core.allocation.models import AllocationAttributeType, \ - AllocationUserAttribute + AllocationUserAttribute, AllocationRenewalRequest, AllocationPeriod, \ + AllocationRenewalRequestStatusChoice from coldfront.core.statistics.models import Job from coldfront.core.user.models import UserProfile from coldfront.core.utils.common import display_time_zone_date_to_utc_datetime from coldfront.core.utils.common import utc_now_offset_aware from coldfront.core.utils.tests.test_base import enable_deployment from coldfront.core.utils.tests.test_base import TestBase -from coldfront.core.allocation.models import AllocationRenewalRequest, AllocationPeriod, \ - AllocationRenewalRequestStatusChoice from coldfront.core.project.models import Project, ProjectStatusChoice, \ ProjectUser, ProjectUserStatusChoice, ProjectUserRoleChoice, \ ProjectAllocationRequestStatusChoice, SavioProjectAllocationRequest, \ @@ -1120,8 +1119,10 @@ def test_get_renewal_survey_responses_csv(self): reader = DictReader(out.readlines()) for index, item in enumerate(reader): project_name = item.pop('project_name') - item.pop('project_title') - item.pop('project_pi') + project_title = item.pop('project_title') + project_pi = item.pop('project_pi') + self.assertEqual(project_title, self.fixtures[index].pre_project.title) + self.assertEqual(project_pi, self.fixtures[index].pi.username) self.assertEqual(project_name, self.fixtures[index].pre_project.name) self.assertEqual(len(item), len(self.fixtures[index].renewal_survey_answers)) sample = ("6. Based upon your overall experience using BRC services, how likely are you" @@ -1146,7 +1147,7 @@ def test_get_renewal_survey_responses_allowance_type(self): project_name = item.pop('project_name') self.assertEqual(project_name, self.filtered_fixtures[index].pre_project.name) self.assertEqual(item['renewal_survey_responses'], - self.swap_form_answer_id_for_text(self.filtered_fixtures[index].renewal_survey_answers)) + self.swap_form_answer_id_for_text(self.filtered_fixtures[index].renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') @@ -1161,7 +1162,7 @@ def swap_form_answer_id_for_text(survey): Parameter ---------- - _survey : survey to modify + survey : survey to modify ''' multiple_choice_fields = {} form = ProjectRenewalSurveyForm() From e28dc91dd3238b67891e2c85259f870f0959d5e4 Mon Sep 17 00:00:00 2001 From: Rae Xin Date: Mon, 20 May 2024 14:17:25 -0700 Subject: [PATCH 7/7] Minor code style changes - shorter lines, removed redundant code, single quotes, excess indentation --- .../core/utils/tests/test_export_data.py | 131 ++++++++++-------- 1 file changed, 72 insertions(+), 59 deletions(-) diff --git a/coldfront/core/utils/tests/test_export_data.py b/coldfront/core/utils/tests/test_export_data.py index 2d5e0d2a1..8df3cd057 100644 --- a/coldfront/core/utils/tests/test_export_data.py +++ b/coldfront/core/utils/tests/test_export_data.py @@ -1007,7 +1007,8 @@ def test_get_new_project_survey_responses_allowance_type(self): self.assertEqual(err.read(), '') class TestRenewalSurveyResponses(TestBase): - """ Test class to test export data subcommand renewal_survey_responses runs correctly """ + """ Test class to test export data subcommand renewal_survey_responses + runs correctly """ @enable_deployment('BRC') def setUp(self): @@ -1016,44 +1017,43 @@ def setUp(self): fixtures = [] filtered_fixtures = [] - allocation_period = AllocationPeriod.objects.get(name__exact='Allowance Year 2024 - 2025') + allocation_period = AllocationPeriod.objects.get( + name__exact='Allowance Year 2024 - 2025') for index in range(5): - pi = User.objects.create( - username=f'test_user{index}', first_name='Test', last_name='User', - is_superuser=True) renewal_survey = { - "brc_feedback": "N/A", - "mybrc_comments": "", - "do_you_use_mybrc": "no", - "classes_being_taught": f"sample answer {index}", - "colleague_suggestions": "N/A", - "grants_supported_by_brc": "Grant #1 etc. etc.\r\nGrant #2 etc. etc.", - "which_brc_services_used": ["savio_hpc", "srdc"], - "indicate_topic_interests": ["have_visited_rdmp_website", - "have_had_rdmp_event_or_consultation", - "want_to_learn_security_and_have_rdm_consult"], - "brc_recommendation_rating": "6", - "publications_supported_by_brc": "N/A", - "which_open_ondemand_apps_used": ["desktop", "matlab", - "jupyter_notebook", "vscode_server"], - "recruitment_or_retention_cases": "N/A", - "brc_recommendation_rating_reason": "Easy to use", - "how_important_to_research_is_brc": "5", - "training_session_other_topics_of_interest": "None", - "how_brc_helped_bootstrap_computational_methods": "N/A", - "training_session_usefulness_of_basic_savio_cluster": "4", - "training_session_usefulness_of_singularity_on_savio": "4", - "training_session_usefulness_of_advanced_savio_cluster": "2", - "training_session_usefulness_of_analytic_envs_on_demand": "5", - "training_session_usefulness_of_computational_platforms_training": "3"} + 'brc_feedback': 'N/A', + 'mybrc_comments': '', + 'do_you_use_mybrc': 'no', + 'classes_being_taught': f'sample answer {index}', + 'colleague_suggestions': 'N/A', + 'grants_supported_by_brc': 'Grant #1 etc. etc.\r\nGrant #2 etc. etc.', + 'which_brc_services_used': ['savio_hpc', 'srdc'], + 'indicate_topic_interests': ['have_visited_rdmp_website', + 'have_had_rdmp_event_or_consultation', + 'want_to_learn_security_and_have_rdm_consult'], + 'brc_recommendation_rating': '6', + 'publications_supported_by_brc': 'N/A', + 'which_open_ondemand_apps_used': ['desktop', 'matlab', + 'jupyter_notebook', 'vscode_server'], + 'recruitment_or_retention_cases': 'N/A', + 'brc_recommendation_rating_reason': 'Easy to use', + 'how_important_to_research_is_brc': '5', + 'training_session_other_topics_of_interest': 'None', + 'how_brc_helped_bootstrap_computational_methods': 'N/A', + 'training_session_usefulness_of_basic_savio_cluster': '4', + 'training_session_usefulness_of_singularity_on_savio': '4', + 'training_session_usefulness_of_advanced_savio_cluster': '2', + 'training_session_usefulness_of_analytic_envs_on_demand': '5', + 'training_session_usefulness_of_computational_platforms_training': '3'} active_project_status = ProjectStatusChoice.objects.get(name='Active') project_prefix = 'fc_' if index % 2 else 'pc_' - project = Project.objects.create(name=f'{project_prefix}test_project{index}', - status=active_project_status) + project = Project.objects.create( + name=f'{project_prefix}test_project{index}', + status=active_project_status) requester = User.objects.create( email=f'requester{index}@email.com', @@ -1084,8 +1084,10 @@ def setUp(self): if index % 2: filtered_fixtures.append(fixture) - fixtures = list(sorted(fixtures, key=lambda x: x.pre_project.name, reverse=True)) - filtered_fixtures = list(sorted(filtered_fixtures, key=lambda x: x.pre_project.name, reverse=True)) + fixtures = list(sorted( + fixtures, key=lambda x: x.pre_project.name, reverse=True)) + filtered_fixtures = list(sorted( + filtered_fixtures, key=lambda x: x.pre_project.name, reverse=True)) self.fixtures = fixtures self.filtered_fixtures = filtered_fixtures @@ -1093,7 +1095,8 @@ def setUp(self): def test_get_renewal_survey_responses_json(self): out, err = StringIO(''), StringIO('') call_command('export_data', 'renewal_survey_responses', - '--format=json', '--allocation_period=Allowance Year 2024 - 2025', + '--format=json', + '--allocation_period=Allowance Year 2024 - 2025', stdout=out, stderr=err) sys.stdout = sys.__stdout__ @@ -1101,9 +1104,11 @@ def test_get_renewal_survey_responses_json(self): output = json.loads(''.join(out.readlines())) for index, item in enumerate(output): project_name = item.pop('project_name') - self.assertEqual(project_name, self.fixtures[index].pre_project.name) + fixture = self.fixtures[index] + self.assertEqual(project_name, fixture.pre_project.name) self.assertEqual(item['renewal_survey_responses'], - self.swap_form_answer_id_for_text(self.fixtures[index].renewal_survey_answers)) + self.swap_form_answer_id_for_text( + fixture.renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') @@ -1111,7 +1116,8 @@ def test_get_renewal_survey_responses_json(self): def test_get_renewal_survey_responses_csv(self): out, err = StringIO(''), StringIO('') call_command('export_data', 'renewal_survey_responses', - '--format=csv', '--allocation_period=Allowance Year 2024 - 2025', + '--format=csv', + '--allocation_period=Allowance Year 2024 - 2025', stdout=out, stderr=err) sys.stdout = sys.__stdout__ @@ -1121,13 +1127,15 @@ def test_get_renewal_survey_responses_csv(self): project_name = item.pop('project_name') project_title = item.pop('project_title') project_pi = item.pop('project_pi') - self.assertEqual(project_title, self.fixtures[index].pre_project.title) - self.assertEqual(project_pi, self.fixtures[index].pi.username) - self.assertEqual(project_name, self.fixtures[index].pre_project.name) - self.assertEqual(len(item), len(self.fixtures[index].renewal_survey_answers)) - sample = ("6. Based upon your overall experience using BRC services, how likely are you" - " to recommend Berkeley Research Computing to others?") - sample_answer = "6" + fixture = self.fixtures[index] + self.assertEqual(project_title, fixture.pre_project.title) + self.assertEqual(project_pi, fixture.pi.username) + self.assertEqual(project_name, fixture.pre_project.name) + self.assertEqual(len(item), len(fixture.renewal_survey_answers)) + sample = ('6. Based upon your overall experience using BRC ' + 'services, how likely are you to recommend Berkeley ' + 'Research Computing to others?') + sample_answer = '6' self.assertEqual(item[sample], sample_answer) err.seek(0) @@ -1137,7 +1145,8 @@ def test_get_renewal_survey_responses_csv(self): def test_get_renewal_survey_responses_allowance_type(self): out, err = StringIO(''), StringIO('') call_command('export_data', 'renewal_survey_responses', - '--format=json', '--allocation_period=Allowance Year 2024 - 2025', + '--format=json', + '--allocation_period=Allowance Year 2024 - 2025', '--allowance_type=fc_', stdout=out, stderr=err) sys.stdout = sys.__stdout__ @@ -1145,9 +1154,11 @@ def test_get_renewal_survey_responses_allowance_type(self): output = json.loads(''.join(out.readlines())) for index, item in enumerate(output): project_name = item.pop('project_name') - self.assertEqual(project_name, self.filtered_fixtures[index].pre_project.name) + fixture = self.filtered_fixtures[index] + self.assertEqual(project_name, fixture.pre_project.name) self.assertEqual(item['renewal_survey_responses'], - self.swap_form_answer_id_for_text(self.filtered_fixtures[index].renewal_survey_answers)) + self.swap_form_answer_id_for_text( + fixture.renewal_survey_answers)) err.seek(0) self.assertEqual(err.read(), '') @@ -1167,19 +1178,21 @@ def swap_form_answer_id_for_text(survey): multiple_choice_fields = {} form = ProjectRenewalSurveyForm() for k, v in form.fields.items(): - # Only ChoiceField or MultipleChoiceField (in this specific survey form) have choices - if (isinstance(v, forms.MultipleChoiceField)) or (isinstance(v, forms.ChoiceField)): - multiple_choice_fields[k] = {_k: _v for _k, _v in form.fields[k].choices} + # Only ChoiceField or MultipleChoiceField + # (in this specific survey form) have choices + if (isinstance(v, (forms.MultipleChoiceField, forms.ChoiceField))): + multiple_choice_fields[k] = { + _k: _v for _k, _v in form.fields[k].choices} for question, answer in survey.items(): - if question in multiple_choice_fields.keys(): - sub_map = multiple_choice_fields[question] - if (isinstance(answer, list)): - # Multiple choice, array - survey[question] = [sub_map.get(i,i) for i in answer] - elif answer != "": - # Single choice replacement - survey[question] = sub_map[answer] - # Change keys of survey (question IDs) to be the human-readable text + if question in multiple_choice_fields.keys(): + sub_map = multiple_choice_fields[question] + if (isinstance(answer, list)): + # Multiple choice, array + survey[question] = [sub_map.get(i,i) for i in answer] + elif answer != '': + # Single choice replacement + survey[question] = sub_map[answer] + # Change keys of survey (question IDs) to be the human-readable text for id, text in form.fields.items(): survey[text.label] = survey.pop(id) return survey \ No newline at end of file