From b2acb8485511d8c3e1ba11024912e0cacea854de Mon Sep 17 00:00:00 2001 From: Hassan Javeed Date: Wed, 16 Mar 2022 02:39:00 +0500 Subject: [PATCH] feat: Added management command dump_course_ids_with_filter. --- .../commands/dump_course_ids_with_filter.py | 35 +++++++++++++++++++ .../commands/tests/test_dump_course.py | 28 +++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 lms/djangoapps/courseware/management/commands/dump_course_ids_with_filter.py diff --git a/lms/djangoapps/courseware/management/commands/dump_course_ids_with_filter.py b/lms/djangoapps/courseware/management/commands/dump_course_ids_with_filter.py new file mode 100644 index 0000000000..c4ed14f431 --- /dev/null +++ b/lms/djangoapps/courseware/management/commands/dump_course_ids_with_filter.py @@ -0,0 +1,35 @@ +""" +Dump the course_ids available to the lms, excluding courses +that have ended prior to the given date. + +Output is UTF-8 encoded by default. +The output format is one course_id per line. +""" + +import datetime + +from textwrap import dedent + +from django.core.management.base import BaseCommand +from django.db.models import Q +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview + + +class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docstring + help = dedent(__doc__).strip() + + def add_arguments(self, parser): + parser.add_argument('--end', + default=None, + help='Date to filter out courses that have ended before the provided date') + + def handle(self, *args, **options): + course_overviews = CourseOverview.objects.all() + courseoverview_filter = Q() + if options['end']: + courseoverview_filter |= Q(end__gte=datetime.datetime.strptime(options['end'], "%Y-%m-%d")) + courseoverview_filter |= Q(end=None) + course_overviews = course_overviews.filter(courseoverview_filter) + + output = '\n'.join(str(course_overview.id) for course_overview in course_overviews) + '\n' + return output diff --git a/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py b/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py index 18e29123b2..9be179bf4a 100644 --- a/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py +++ b/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py @@ -2,11 +2,12 @@ Tests for Django management commands """ - +import datetime import json from io import StringIO import factory +import pytz from django.conf import settings from django.core.management import call_command @@ -22,6 +23,8 @@ from xmodule.modulestore.xml_importer import import_course_from_xml DATA_DIR = settings.COMMON_TEST_DATA_ROOT XML_COURSE_DIRS = ['simple'] +TEST_COURSE_START = datetime.datetime(2012, 7, 1, tzinfo=pytz.UTC) +TEST_COURSE_END = datetime.datetime(2012, 12, 31, tzinfo=pytz.UTC) class CommandsTestBase(SharedModuleStoreTestCase): @@ -56,7 +59,9 @@ class CommandsTestBase(SharedModuleStoreTestCase): course='simple', run="run", display_name='2012_Fáĺĺ', - modulestore=store + modulestore=store, + start=TEST_COURSE_START, + end=TEST_COURSE_END, ) cls.discussion = ItemFactory.create( @@ -81,6 +86,25 @@ class CommandsTestBase(SharedModuleStoreTestCase): out.seek(0) return out.read() + def test_dump_course_ids_with_filter(self): + """ + Test that `dump_course_ids_with_filter` works correctly by + only returning courses that have not ended before the provided `end` data. + + `load_courses` method creates two courses first by calling CourseFactory.create + which creates a course with end=2012-12-31. Then it creates a second course + by calling import_course_from_xml which creates a course with end=None. + + This test makes sure that only the second course is returned when + `end`=2013-01-01 is passed to `dump_course_ids_with_filter`. + """ + args = [] + kwargs = {'end': '2013-01-01'} # exclude any courses which have ended before 2013-01-01 + output = self.call_command('dump_course_ids_with_filter', *args, **kwargs) + dumped_courses = output.strip().split('\n') + dumped_ids = set(dumped_courses) + assert {str(self.test_course_key)} == dumped_ids + def test_dump_course_ids(self): output = self.call_command('dump_course_ids') dumped_courses = output.strip().split('\n')