def test_post_all_fields(self): data = { 'server_url': self.STR_MY_SITE, 'include_no_courses': True, 'include_no_users': True, 'email_notifications': True, 'notif_email_address': self.STR_MY_EMAIL } self.client.force_login(user=self.admin_user) response = self.client.post(self.url_register_page, data) self.assertRedirects(response, self.url_thanks_page, 302, 200) # check data saved correctly self.assertEqual( self.STR_MY_SITE, SettingProperties.get_property(constants.OPPIA_HOSTNAME, '')) self.assertTrue( SettingProperties.get_property( constants.OPPIA_SERVER_REGISTER_NO_COURSES, False)) self.assertTrue( SettingProperties.get_property( constants.OPPIA_SERVER_REGISTER_NO_USERS, False)) self.assertTrue( SettingProperties.get_property( constants.OPPIA_SERVER_REGISTER_EMAIL_NOTIF, False)) self.assertEqual( self.STR_MY_EMAIL, SettingProperties.get_property( constants.OPPIA_SERVER_REGISTER_NOTIF_EMAIL_ADDRESS, ''))
def handle(self, *args, **options): # check if cron already running prop, created = SettingProperties.objects \ .get_or_create(key='oppia_summary_cron_lock', int_value=1) if not created: self.stdout.write("Oppia summary cron is already running") return try: SettingProperties.objects.get(key='oppia_cron_lock') self.stdout.write("Oppia cron is already running") SettingProperties.delete_key('oppia_summary_cron_lock') return except SettingProperties.DoesNotExist: # do nothing pass if options['fromstart']: self.update_summaries(0, 0) else: # get last tracker and points PKs processed last_tracker_pk = SettingProperties.get_property( 'last_tracker_pk', 0) last_points_pk = SettingProperties.get_property( 'last_points_pk', 0) self.update_summaries(last_tracker_pk, last_points_pk)
def handle(self, *args, **options): if options['fromstart']: update_summaries(0, 0) else: # get last tracker and points PKs processed last_tracker_pk = SettingProperties.get_property('last_tracker_pk', 0) last_points_pk = SettingProperties.get_property('last_points_pk', 0) update_summaries(last_tracker_pk, last_points_pk)
def run(): print('Starting Oppia Summary cron...') start = time.time() from settings.models import SettingProperties # get last tracker and points PKs processed last_tracker_pk = SettingProperties.get_property('last_tracker_pk', 0) last_points_pk = SettingProperties.get_property('last_points_pk', 0) update_summaries(last_tracker_pk, last_points_pk) elapsed_time = time.time() - start print('cron completed, took %.2f seconds' % elapsed_time)
def run(): print('Starting Oppia Summary cron...') start = time.time() from settings.models import SettingProperties # get last tracker and points PKs processed last_tracker_pk = SettingProperties.get_property('last_tracker_pk', 0) last_points_pk = SettingProperties.get_property('last_points_pk', 0) update_summaries(last_tracker_pk, last_points_pk) elapsed_time = time.time() - start print('cron completed, took %.2f seconds' % elapsed_time)
def handle(self, *args, **options): """ Populates the course_version field in the tracker model based on the current course activities """ newest_tracker_pk = Tracker.objects.latest('id').id init_tracker_pk = SettingProperties.get_property( 'last_courseversion_populated_tracker_pk', 0) if newest_tracker_pk <= init_tracker_pk: print("No more trackers to process!") return trackers = Tracker.objects.filter(digest__isnull=False, pk__gt=init_tracker_pk, course__isnull=False, course_version__isnull=True) print("{} total trackers to process".format(trackers.count())) while newest_tracker_pk > init_tracker_pk: end_tracker_pk = min(init_tracker_pk + BATCH_PROCESS_SIZE, newest_tracker_pk) self.process_batch(init_tracker_pk, end_tracker_pk) SettingProperties.set_int( 'last_courseversion_populated_tracker_pk', end_tracker_pk) init_tracker_pk = end_tracker_pk
def test_get_prop_string_doesnotexist(self): key = "testkey" value = "mystring" SettingProperties.set_string(key, value) retreived_value = SettingProperties.get_property("some non key", "not here") self.assertEqual("not here", retreived_value)
def handle(self, *args, **options): years = SettingProperties.get_property( constants.OPPIA_DATA_RETENTION_YEARS, 999) print(commands.TERMINAL_COLOUR_WARNING) print( _(u"WARNING! This script will delete any user profiles and " + u"tracker data for users who have not logged in or had any " + u"tracker logs recorded for the last %d years") % years) print(commands.TERMINAL_COLOUR_ENDC) if not options['noinput']: accept = input(_(u"Would you like to continue? [y/n]")) if accept != 'y': print(_(u"Aborting")) return users_to_delete = self.get_users_to_delete(years) users_removed = 0 if len(users_to_delete) > 0: users_removed = self.delete_users(options, users_to_delete) else: print(_(u"There are no users to remove")) if users_removed > 0: self.run_summaries(options)
def process(self, request, form, start_date, end_date): data = {} total_users = DailyActiveUser.objects.filter( user__is_staff=False, user__is_superuser=False).values("user").distinct().count() if total_users == 0: return render(request, 'reports/inactive_users.html', {'form': form}) data['total_users'] = total_users one_month_date = end_date - datetime.timedelta(days=31) active_one_month = DailyActiveUser.objects.filter( user__is_staff=False, user__is_superuser=False, dau__day__gte=one_month_date).values("user").distinct().count() data['inactive_one_month_no'] = total_users - active_one_month data['inactive_one_month_percent'] = \ int((total_users - active_one_month) * 100 / total_users) three_month_date = end_date - datetime.timedelta(days=91) active_three_month = DailyActiveUser.objects.filter( user__is_staff=False, user__is_superuser=False, dau__day__gte=three_month_date).values("user").distinct().count() data['inactive_three_month_no'] = total_users - active_three_month data['inactive_three_month_percent'] = \ int((total_users - active_three_month) * 100 / total_users) six_month_date = end_date - datetime.timedelta(days=183) active_six_month = DailyActiveUser.objects.filter( user__is_staff=False, user__is_superuser=False, dau__day__gte=six_month_date).values("user").distinct().count() data['inactive_six_month_no'] = total_users - active_six_month data['inactive_six_month_percent'] = \ int((total_users - active_six_month) * 100 / total_users) data['years'] = [] for i in range(1, SettingProperties.get_property( constants.OPPIA_DATA_RETENTION_YEARS, 999) + 1): days = i * 365 year_date = end_date - datetime.timedelta(days=days) active_years = DailyActiveUser.objects.filter( user__is_staff=False, user__is_superuser=False, dau__day__gte=year_date).values("user").distinct().count() year_data = {} year_data['year'] = i year_data['inactive_no'] = total_users - active_years year_data['inactive_percent'] = \ int((total_users - active_years) * 100 / total_users) data['years'].append(year_data) return render(request, 'reports/inactive_users.html', {'inactive_user_data': data, 'form': form})
def process(self, course, badge, hours): quiz_digests = Activity.objects.filter(section__course=course, type=Activity.QUIZ) \ .values('digest') \ .distinct() other_digests = Activity.objects \ .filter(section__course=course).exclude(type=Activity.QUIZ) \ .values('digest') \ .distinct() # get all the users who've added tracker for this course in last # 'hours' if hours == 0: users = User.objects.filter(tracker__course=course) else: since = timezone.now() - datetime.timedelta(hours=int(hours)) users = User.objects.filter(tracker__course=course, tracker__submitted_date__gte=since) # exclude the users that already own this course award users = users.exclude(award__awardcourse__course=course).distinct() for user in users: # check all quizzes have been completed user_completed_quizzes = Tracker.objects.filter( user=user, course=course, completed=True, type=Activity.QUIZ, digest__in=quiz_digests) \ .values('digest') \ .distinct() \ .count() # check percentage of other activities completed user_completed_other = Tracker.objects.filter( user=user, course=course, completed=True, digest__in=other_digests) \ .exclude(type=Activity.QUIZ) \ .values('digest') \ .distinct() \ .count() percent_complete = (user_completed_other / len(other_digests)) * 100 if quiz_digests.count() == user_completed_quizzes and \ percent_complete >= SettingProperties.get_property( constants.OPPIA_BADGES_PERCENT_COMPLETED, 80): self.award_badge(course, user, badge)
def check_old_quizzes(self): years = SettingProperties.get_property( constants.OPPIA_DATA_RETENTION_YEARS, 999) archive_date = timezone.now() - relativedelta(years=years) quizzes = Quiz.objects.filter(created_date__lte=archive_date) for quiz in quizzes: qas = QuizAttempt.objects.filter(quiz=quiz, user__is_staff=False) if qas.count() == 0: print( _(u"Deleting quiz {}, as it was created over {} years " "ago and has no attempts").format(quiz.title, years)) self.delete_quiz(quiz)
def get_graph_data(self, start_date, end_date): data = {} total_users = UserCourseDailySummary.objects\ .exclude(user__in=self.users_filter_by)\ .values('user').distinct().count() if total_users == 0: return {} data['total_users'] = total_users active_last_month = self.users_active_since(end_date - datetime.timedelta( days=31)) data['inactive_one_month_no'] = total_users - active_last_month data['inactive_one_month_percent'] = int( (total_users - active_last_month) * 100 / total_users) active_three_month = self.users_active_since(end_date - datetime.timedelta( days=91)) data['inactive_three_month_no'] = total_users - active_three_month data['inactive_three_month_percent'] = int( (total_users - active_three_month) * 100 / total_users) active_six_month = self.users_active_since(end_date - datetime.timedelta( days=183)) data['inactive_six_month_no'] = total_users - active_six_month data['inactive_six_month_percent'] = int( (total_users - active_six_month) * 100 / total_users) data['years'] = [] for i in range( 1, SettingProperties.get_property( constants.OPPIA_DATA_RETENTION_YEARS, 999) + 1): days = i * 365 year_date = end_date - datetime.timedelta(days=days) active_years = self.users_active_since(year_date) year_data = {} year_data['year'] = i year_data['inactive_no'] = total_users - active_years year_data['inactive_percent'] = int( (total_users - active_years) * 100 / total_users) data['years'].append(year_data) return {'inactive_user_data': data}
def test_update_server_unregistered(self): api_key_response = get_file_contents(self.get_api_key_valid_response) httpretty.register_uri(httpretty.GET, self.get_api_key_uri_regex, body=api_key_response) update_response = get_file_contents(self.update_valid_response) httpretty.register_uri(httpretty.POST, self.update_uri_regex, body=update_response) out = StringIO() call_command(self.STR_COMMAND, stdout=out) # check api key matches the one returned api_key = SettingProperties.get_property( constants.OPPIA_SERVER_REGISTER_APIKEY, '') self.assertEqual('', api_key)
def get_initial(self): initial = { 'server_url': SettingProperties.get_property(constants.OPPIA_HOSTNAME, ''), 'include_no_courses': SettingProperties.get_bool( constants.OPPIA_SERVER_REGISTER_NO_COURSES, False), 'include_no_users': SettingProperties.get_bool( constants.OPPIA_SERVER_REGISTER_NO_USERS, False), 'email_notifications': SettingProperties.get_bool( constants.OPPIA_SERVER_REGISTER_EMAIL_NOTIF, False), 'notif_email_address': SettingProperties.get_string( constants.OPPIA_SERVER_REGISTER_NOTIF_EMAIL_ADDRESS, '') } return initial
def test_update_server_registered(self): api_key_response = get_file_contents(self.get_api_key_valid_response) httpretty.register_uri(httpretty.GET, self.get_api_key_uri_regex, body=api_key_response) update_response = get_file_contents(self.update_valid_response) httpretty.register_uri(httpretty.POST, self.update_uri_regex, body=update_response) SettingProperties.set_bool(constants.OPPIA_SERVER_REGISTERED, True) SettingProperties.set_bool(constants.OPPIA_SERVER_REGISTER_EMAIL_NOTIF, True) SettingProperties.set_bool(constants.OPPIA_SERVER_REGISTER_NO_COURSES, True) SettingProperties.set_bool(constants.OPPIA_SERVER_REGISTER_NO_USERS, True) out = StringIO() call_command(self.STR_COMMAND, stdout=out) # check api key matches the one returned api_key = SettingProperties.get_property( constants.OPPIA_SERVER_REGISTER_APIKEY, '') self.assertEqual('AwZfRgB.rxpVnadfn8K6sgY8qYOp8', api_key)
def test_get_prop_int_none(self): key = "testkey" value = None SettingProperties.set_int(key, value) retreived_value = SettingProperties.get_property(key, 100) self.assertEqual(100, retreived_value)
def test_get_prop_string_none(self): key = "testkey" value = None SettingProperties.set_string(key, value) retreived_value = SettingProperties.get_property(key, "default") self.assertEqual("default", retreived_value)
def test_get_prop_int(self): key = "testkey" value = 123 SettingProperties.set_int(key, value) retreived_value = SettingProperties.get_property(key, 0) self.assertEqual(value, retreived_value)
def test_get_prop_int_doesnotexist(self): key = "testkey" value = 123 SettingProperties.set_int(key, value) retreived_value = SettingProperties.get_property("some non key", 100) self.assertEqual(100, retreived_value)
def settings_value(name): if name in ALLOWABLE_SETTING_VALUES: return getattr(settings, name, '') if name in ALLOWABLE_DB_SETTINGS: return SettingProperties.get_property(name, None) return ''