Files
edx-platform/cms/djangoapps/contentstore/management/commands/generate_courses.py
M. Zulqarnain da970bf215 BOM-2369 (B): Pyupgrade on contentstore/management (#26758)
* pyupgrade on contentstore/management
2021-03-04 14:31:10 +05:00

163 lines
6.5 KiB
Python

"""
Django management command to generate a test course from a course config json
"""
import json
import logging
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.core.management.base import BaseCommand, CommandError
from cms.djangoapps.contentstore.management.commands.utils import user_from_str
from cms.djangoapps.contentstore.views.course import create_new_course_in_store
from openedx.core.djangoapps.credit.models import CreditProvider
from xmodule.course_module import CourseFields
from xmodule.fields import Date
from xmodule.modulestore.exceptions import DuplicateCourseError
from xmodule.tabs import CourseTabList
logger = logging.getLogger(__name__)
class Command(BaseCommand):
""" Generate a basic course """
help = 'Generate courses on studio from a json list of courses'
def add_arguments(self, parser):
parser.add_argument(
'courses_json',
)
def handle(self, *args, **options):
try:
courses = json.loads(options["courses_json"])["courses"]
except ValueError:
raise CommandError("Invalid JSON object") # lint-amnesty, pylint: disable=raise-missing-from
except KeyError:
raise CommandError("JSON object is missing courses list") # lint-amnesty, pylint: disable=raise-missing-from
for course_settings in courses:
# Validate course
if not self._course_is_valid(course_settings):
logger.warning("Can't create course, proceeding to next course")
continue
# Retrieve settings
org = course_settings["organization"]
num = course_settings["number"]
run = course_settings["run"]
user_email = course_settings["user"]
try:
user = user_from_str(user_email)
except User.DoesNotExist:
logger.warning(user_email + " user does not exist") # lint-amnesty, pylint: disable=logging-not-lazy
logger.warning("Can't create course, proceeding to next course")
continue
fields = self._process_course_fields(course_settings["fields"])
# Create the course
try:
new_course = create_new_course_in_store("split", user, org, num, run, fields)
logger.info("Created {}".format(str(new_course.id)))
except DuplicateCourseError:
logger.warning("Course already exists for %s, %s, %s", org, num, run)
# Configure credit provider
if ("enrollment" in course_settings) and ("credit_provider" in course_settings["enrollment"]):
credit_provider = course_settings["enrollment"]["credit_provider"]
if credit_provider is not None:
CreditProvider.objects.get_or_create(
provider_id=credit_provider,
display_name=credit_provider
)
def _process_course_fields(self, fields):
""" Returns a validated list of course fields """
all_fields = list(CourseFields.__dict__.keys())
non_course_fields = [
"__doc__",
"__module__",
"__weakref__",
"__dict__"
]
for field in non_course_fields:
all_fields.remove(field)
# Non-primitive course fields
date_fields = [
"certificate_available_date",
"announcement",
"enrollment_start",
"enrollment_end",
"start",
"end"
]
course_tab_list_fields = [
"tabs"
]
for field in dict(fields):
if field not in all_fields:
# field does not exist as a CourseField
del fields[field]
logger.info(field + "is not a valid CourseField") # lint-amnesty, pylint: disable=logging-not-lazy
elif fields[field] is None:
# field is unset
del fields[field]
elif field in date_fields:
# Generate Date object from the json value
try:
date_json = fields[field]
fields[field] = Date().from_json(date_json)
logger.info(field + " has been set to " + date_json)
except Exception: # pylint: disable=broad-except
logger.info("The date string could not be parsed for " + field) # lint-amnesty, pylint: disable=logging-not-lazy
del fields[field]
elif field in course_tab_list_fields:
# Generate CourseTabList object from the json value
try:
course_tab_list_json = fields[field]
fields[field] = CourseTabList().from_json(course_tab_list_json)
logger.info(field + " has been set to " + course_tab_list_json)
except Exception: # pylint: disable=broad-except
logger.info("The course tab list string could not be parsed for " + field) # lint-amnesty, pylint: disable=logging-not-lazy
del fields[field]
else:
# CourseField is valid and has been set
logger.info(field + " has been set to " + str(fields[field])) # lint-amnesty, pylint: disable=logging-not-lazy
for field in all_fields:
if field not in fields:
logger.info(field + " has not been set") # lint-amnesty, pylint: disable=logging-not-lazy
return fields
def _course_is_valid(self, course):
""" Returns true if the course contains required settings """
is_valid = True
# Check course settings
required_course_settings = [
"organization",
"number",
"run",
"fields",
"user"
]
for setting in required_course_settings:
if setting not in course:
logger.warning("Course json is missing " + setting) # lint-amnesty, pylint: disable=logging-not-lazy
is_valid = False
# Check fields settings
required_field_settings = [
"display_name"
]
if "fields" in course:
for setting in required_field_settings:
if setting not in course["fields"]:
logger.warning("Fields json is missing " + setting) # lint-amnesty, pylint: disable=logging-not-lazy
is_valid = False
return is_valid