Skip to content

Commit 8cad408

Browse files
committed
chore: organize code
1 parent 4dee367 commit 8cad408

1 file changed

Lines changed: 104 additions & 104 deletions

File tree

openedx_authz/api/data.py

Lines changed: 104 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,110 @@ def __repr__(self):
526526
return self.namespaced_key
527527

528528

529+
@define
530+
class CourseOverviewData(ScopeData):
531+
"""A course scope for authorization in the Open edX platform.
532+
533+
Courses uses the CourseKey format for identification.
534+
535+
Attributes:
536+
NAMESPACE (str): 'course-v1' for course scopes.
537+
ID_SEPARATOR (str): '+' for course scopes.
538+
external_key (str): The course identifier (e.g., 'course-v1:TestOrg+TestCourse+2024_T1').
539+
Must be a valid CourseKey format.
540+
namespaced_key (str): The course identifier with namespace
541+
(e.g., 'course-v1^course-v1:TestOrg+TestCourse+2024_T1').
542+
course_id (str): Property alias for external_key.
543+
544+
Examples:
545+
>>> course = CourseOverviewData(external_key='course-v1:TestOrg+TestCourse+2024_T1')
546+
>>> course.namespaced_key
547+
'course-v1^course-v1:TestOrg+TestCourse+2024_T1'
548+
>>> course.course_id
549+
'course-v1:TestOrg+TestCourse+2024_T1'
550+
"""
551+
552+
NAMESPACE: ClassVar[str] = "course-v1"
553+
ID_SEPARATOR: ClassVar[str] = "+"
554+
555+
@property
556+
def course_id(self) -> str:
557+
"""The course identifier as used in Open edX (e.g., 'course-v1:TestOrg+TestCourse+2024_T1').
558+
559+
This is an alias for external_key that represents the course ID without the namespace prefix.
560+
561+
Returns:
562+
str: The course identifier without namespace.
563+
"""
564+
return self.external_key
565+
566+
@property
567+
def course_key(self) -> CourseKey:
568+
"""The CourseKey object for the course.
569+
570+
Returns:
571+
CourseKey: The course key object.
572+
"""
573+
return CourseKey.from_string(self.course_id)
574+
575+
@classmethod
576+
def validate_external_key(cls, external_key: str) -> bool:
577+
"""Validate the external_key format for CourseOverviewData.
578+
579+
Args:
580+
external_key: The external key to validate.
581+
582+
Returns:
583+
bool: True if valid, False otherwise.
584+
"""
585+
try:
586+
CourseKey.from_string(external_key)
587+
return True
588+
except InvalidKeyError:
589+
return False
590+
591+
def get_object(self) -> CourseOverview | None:
592+
"""Retrieve the CourseOverview instance associated with this scope.
593+
594+
This method converts the course_id to a CourseKey and queries the
595+
database to fetch the corresponding CourseOverview object.
596+
597+
Returns:
598+
CourseOverview | None: The CourseOverview instance if found in the database,
599+
or None if the course does not exist or has an invalid key format.
600+
601+
Examples:
602+
>>> course_scope = CourseOverviewData(external_key='course-v1:TestOrg+TestCourse+2024_T1')
603+
>>> course_obj = course_scope.get_object() # CourseOverview object
604+
"""
605+
try:
606+
course_obj = CourseOverview.get_from_id(self.course_key)
607+
# Validate canonical key: get_by_key is case-insensitive, but we require exact match
608+
# This ensures authorization uses canonical course IDs consistently
609+
if course_obj.id != self.course_key:
610+
raise CourseOverview.DoesNotExist
611+
except (InvalidKeyError, CourseOverview.DoesNotExist):
612+
return None
613+
614+
return course_obj
615+
616+
def exists(self) -> bool:
617+
"""Check if the course overview exists.
618+
619+
Returns:
620+
bool: True if the course overview exists, False otherwise.
621+
"""
622+
return self.get_object() is not None
623+
624+
def __str__(self):
625+
"""Human readable string representation of the course overview."""
626+
return self.course_id
627+
628+
def __repr__(self):
629+
"""Developer friendly string representation of the course overview."""
630+
return self.namespaced_key
631+
632+
529633
@define
530634
class OrgGlobData(ScopeData):
531635
"""Base class for organization-scoped *glob* scope keys.
@@ -677,110 +781,6 @@ class OrgContentLibraryGlobData(OrgGlobData):
677781
ID_SEPARATOR: ClassVar[str] = ":"
678782

679783

680-
@define
681-
class CourseOverviewData(ScopeData):
682-
"""A course scope for authorization in the Open edX platform.
683-
684-
Courses uses the CourseKey format for identification.
685-
686-
Attributes:
687-
NAMESPACE (str): 'course-v1' for course scopes.
688-
ID_SEPARATOR (str): '+' for course scopes.
689-
external_key (str): The course identifier (e.g., 'course-v1:TestOrg+TestCourse+2024_T1').
690-
Must be a valid CourseKey format.
691-
namespaced_key (str): The course identifier with namespace
692-
(e.g., 'course-v1^course-v1:TestOrg+TestCourse+2024_T1').
693-
course_id (str): Property alias for external_key.
694-
695-
Examples:
696-
>>> course = CourseOverviewData(external_key='course-v1:TestOrg+TestCourse+2024_T1')
697-
>>> course.namespaced_key
698-
'course-v1^course-v1:TestOrg+TestCourse+2024_T1'
699-
>>> course.course_id
700-
'course-v1:TestOrg+TestCourse+2024_T1'
701-
"""
702-
703-
NAMESPACE: ClassVar[str] = "course-v1"
704-
ID_SEPARATOR: ClassVar[str] = "+"
705-
706-
@property
707-
def course_id(self) -> str:
708-
"""The course identifier as used in Open edX (e.g., 'course-v1:TestOrg+TestCourse+2024_T1').
709-
710-
This is an alias for external_key that represents the course ID without the namespace prefix.
711-
712-
Returns:
713-
str: The course identifier without namespace.
714-
"""
715-
return self.external_key
716-
717-
@property
718-
def course_key(self) -> CourseKey:
719-
"""The CourseKey object for the course.
720-
721-
Returns:
722-
CourseKey: The course key object.
723-
"""
724-
return CourseKey.from_string(self.course_id)
725-
726-
@classmethod
727-
def validate_external_key(cls, external_key: str) -> bool:
728-
"""Validate the external_key format for CourseOverviewData.
729-
730-
Args:
731-
external_key: The external key to validate.
732-
733-
Returns:
734-
bool: True if valid, False otherwise.
735-
"""
736-
try:
737-
CourseKey.from_string(external_key)
738-
return True
739-
except InvalidKeyError:
740-
return False
741-
742-
def get_object(self) -> CourseOverview | None:
743-
"""Retrieve the CourseOverview instance associated with this scope.
744-
745-
This method converts the course_id to a CourseKey and queries the
746-
database to fetch the corresponding CourseOverview object.
747-
748-
Returns:
749-
CourseOverview | None: The CourseOverview instance if found in the database,
750-
or None if the course does not exist or has an invalid key format.
751-
752-
Examples:
753-
>>> course_scope = CourseOverviewData(external_key='course-v1:TestOrg+TestCourse+2024_T1')
754-
>>> course_obj = course_scope.get_object() # CourseOverview object
755-
"""
756-
try:
757-
course_obj = CourseOverview.get_from_id(self.course_key)
758-
# Validate canonical key: get_by_key is case-insensitive, but we require exact match
759-
# This ensures authorization uses canonical course IDs consistently
760-
if course_obj.id != self.course_key:
761-
raise CourseOverview.DoesNotExist
762-
except (InvalidKeyError, CourseOverview.DoesNotExist):
763-
return None
764-
765-
return course_obj
766-
767-
def exists(self) -> bool:
768-
"""Check if the course overview exists.
769-
770-
Returns:
771-
bool: True if the course overview exists, False otherwise.
772-
"""
773-
return self.get_object() is not None
774-
775-
def __str__(self):
776-
"""Human readable string representation of the course overview."""
777-
return self.course_id
778-
779-
def __repr__(self):
780-
"""Developer friendly string representation of the course overview."""
781-
return self.namespaced_key
782-
783-
784784
@define
785785
class OrgCourseOverviewGlobData(OrgGlobData):
786786
"""Organization-level glob pattern for courses.

0 commit comments

Comments
 (0)