Skip to content

Commit

Permalink
Merge pull request #18 from openfun/gradereport_user_get_grade_items
Browse files Browse the repository at this point in the history
Implements gradereport_user_get_grade_items wsfunction
  • Loading branch information
hexatester authored Aug 30, 2023
2 parents b073937 + 6f7a96b commit 8d98837
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 0 deletions.
2 changes: 2 additions & 0 deletions moodle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .core import Core
from .enrol import Enrol
from .mod import Mod
from .gradereport import GradeReport

from .mdl import Mdl
from .moodle import Moodle
Expand All @@ -38,6 +39,7 @@
"Core",
"Block",
"Enrol",
"GradeReport",
"Mod",
"Tool",
"Mdl",
Expand Down
5 changes: 5 additions & 0 deletions moodle/gradereport/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .user import BaseGradeReportUser

from .gradereport import GradeReport

__all__ = ["BaseGradeReportUser", "GradeReport"]
10 changes: 10 additions & 0 deletions moodle/gradereport/gradereport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from moodle import BaseMoodle
from moodle.utils.decorator import lazy
from . import BaseGradeReportUser


class GradeReport(BaseMoodle):
@property
@lazy
def user(self) -> BaseGradeReportUser:
return BaseGradeReportUser(self.moodle)
3 changes: 3 additions & 0 deletions moodle/gradereport/user/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .base import BaseGradeReportUser

__all__ = ["BaseGradeReportUser"]
31 changes: 31 additions & 0 deletions moodle/gradereport/user/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from typing import Optional

from moodle import BaseMoodle
from moodle.gradereport.user.gradereport import GradeReport


class BaseGradeReportUser(BaseMoodle):
def get_user_grades(
self,
course_id: int,
user_id: Optional[int] = None,
group_id: Optional[int] = None,
) -> GradeReport:
"""Get user grades for a course.
Args:
course_id (int): course id
user_id (int, optional): user id. Defaults to None.
group_id (int, optional): group id. Defaults to None.
Returns:
GradeReport: Returns the complete list of grade items for users
in a course
"""
data = self.moodle.post(
"gradereport_user_get_grade_items",
courseid=course_id,
userid=user_id,
groupid=group_id,
)
return self._tr(GradeReport, **data)
112 changes: 112 additions & 0 deletions moodle/gradereport/user/gradereport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from moodle.attr import dataclass, field
from typing import List, Optional


@dataclass
class GradeItem:
"""Grade Item
Args:
id (int): Grade item id
itemname (string): Grade item name
itemtype (string): Grade item type
itemmodule (string): Grade item module
iteminstance (int): Grade item instance
itemnumber (int): Grade item item number
idnumber (string): Grade item idnumber
categoryid (int): Grade item category id
outcomeid (int): Outcome id
scaleid (int): Scale id
locked (Optional[int]): Grade item for user locked?
cmid (Optional[int]): Course module id (if type mod)
weightraw (Optional[int]): Weight raw
weightformatted (Optional[string]): Weight
status (Optional[string]): Status
graderaw (Optional[int]): Grade raw
gradedatesubmitted (Optional[int]): Grade submit date
gradedategraded (Optional[int]): Grade graded date
gradehiddenbydate (Optional[int]): Grade hidden by date?
gradeneedsupdate (Optional[int]): Grade needs update?
gradeishidden (Optional[int]): Grade is hidden?
gradeislocked (Optional[int]): Grade is locked?
gradeisoverridden (Optional[int]): Grade overridden?
gradeformatted (Optional[string]): The grade formatted
grademin (Optional[int]): Grade min
grademax (Optional[int]): Grade max
rangeformatted (Optional[string]): Range formatted
percentageformatted (Optional[string]): Percentage
lettergradeformatted (Optional[string]): Letter grade
rank (Optional[int]): Rank in the course
numusers (Optional[int]): Num users in course
averageformatted (Optional[string]): Grade average
feedback (Optional[string]): Grade feedback
feedbackformat (Optional[int]): feedback format
(1 = HTML, 0 = MOODLE, 2 = PLAIN, or 4 = MARKDOWN
"""

feedback: str
feedbackformat: int
gradeformatted: str
gradehiddenbydate: bool
gradeishidden: bool
gradeislocked: bool
gradeisoverridden: bool
grademax: int
grademin: int
gradeneedsupdate: bool
id: int
idnumber: str
iteminstance: int
itemmodule: str
itemname: str
itemtype: str
locked: bool
percentageformatted: str
rangeformatted: str
categoryid: Optional[int] = None
cmid: Optional[int] = None
gradedategraded: Optional[int] = None
gradedatesubmitted: Optional[int] = None
graderaw: Optional[int] = None
itemnumber: Optional[int] = None
outcomeid: Optional[int] = None
scaleid: Optional[int] = None
weightformatted: Optional[str] = None
weightraw: Optional[int] = None


@dataclass
class UserGrade:
"""User Grade
Args:
courseid (int): course id
courseidnumber (string): course idnumber
gradeitems (List[GradeItem]): Grade items
maxdepth (int): table max depth (needed for printing it)
userfullname (string): user fullname
userid (int): user id
useridnumber (string): user idnumber
"""

courseid: int
courseidnumber: str
gradeitems: List[GradeItem]
maxdepth: int
userfullname: str
userid: int
useridnumber: str


@dataclass
class GradeReport:
"""Grade Report
Args:
usergrades (List[UserGrade]): List of user grades
warnings (List[Warning]): List of warnings
"""

usergrades: List[UserGrade] = field(factory=list)
warnings: List[Warning] = field(factory=list)
6 changes: 6 additions & 0 deletions moodle/moodle.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from moodle.block import Block
from moodle.core import Core
from moodle.enrol import Enrol
from moodle.gradereport import GradeReport
from moodle.mod import Mod
from moodle.tool import Tool

Expand Down Expand Up @@ -39,6 +40,11 @@ def core(self) -> Core:
def enrol(self) -> Enrol:
return Enrol(self)

@property # type: ignore
@lazy
def grade_report(self) -> GradeReport:
return GradeReport(self)

@property # type: ignore
@lazy
def mod(self) -> Mod:
Expand Down
72 changes: 72 additions & 0 deletions tests/test_core/test_grades.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from moodle.gradereport.user.gradereport import UserGrade, GradeItem, GradeReport


class TestGrades:
def test_get_grades(self, moodle, courses):
grades = moodle.grade_report.user.get_user_grades(course_id=courses[-1].id)
assert grades is not None
assert isinstance(grades, GradeReport)
assert grades.usergrades is not None
assert type(grades.usergrades) == list
for user_grade in grades.usergrades:
assert isinstance(user_grade, UserGrade)
assert isinstance(user_grade.courseid, int)
assert isinstance(user_grade.courseidnumber, str)
assert isinstance(user_grade.gradeitems, list)
assert isinstance(user_grade.maxdepth, int)
assert isinstance(user_grade.userfullname, str)
assert isinstance(user_grade.userid, int)
assert isinstance(user_grade.useridnumber, str)

for grade_item in user_grade.gradeitems:
assert isinstance(grade_item, GradeItem)
assert not grade_item.categoryid or isinstance(
grade_item.categoryid, int
)
assert not grade_item.cmid or isinstance(grade_item.cmid, int)
assert isinstance(grade_item.feedback, str)
assert isinstance(grade_item.feedbackformat, int)
assert not grade_item.gradedategraded or isinstance(
grade_item.gradedategraded, int
)
assert not grade_item.gradedatesubmitted or isinstance(
grade_item.gradedatesubmitted, int
)
assert isinstance(grade_item.gradeformatted, str)
assert isinstance(grade_item.gradehiddenbydate, bool)
assert isinstance(grade_item.gradeishidden, bool)
assert isinstance(grade_item.gradeislocked, bool)
assert isinstance(grade_item.gradeisoverridden, bool)
assert isinstance(grade_item.grademax, int)
assert isinstance(grade_item.grademin, int)
assert isinstance(grade_item.gradeneedsupdate, bool)
assert not grade_item.graderaw or isinstance(grade_item.graderaw, int)
assert isinstance(grade_item.id, int)
assert isinstance(grade_item.idnumber, str)
assert isinstance(grade_item.iteminstance, int)
assert isinstance(grade_item.itemmodule, str)
assert isinstance(grade_item.itemname, str)
assert not grade_item.itemnumber or isinstance(
grade_item.itemnumber, int
)
assert isinstance(grade_item.itemtype, str)
assert isinstance(grade_item.locked, bool)
assert isinstance(grade_item.percentageformatted, str)
assert isinstance(grade_item.rangeformatted, str)
assert not grade_item.weightformatted or isinstance(
grade_item.weightformatted, str
)
assert not grade_item.weightraw or isinstance(grade_item.weightraw, int)
assert not grade_item.outcomeid or isinstance(grade_item.outcomeid, int)
assert not grade_item.scaleid or isinstance(grade_item.scaleid, int)

def test_get_grades_user_filtered(self, moodle, courses):
grades = moodle.grade_report.user.get_user_grades(
course_id=courses[-1].id, user_id=47
)
assert grades is not None
assert isinstance(grades, GradeReport)
assert grades.usergrades is not None
assert type(grades.usergrades) == list
assert len(grades.usergrades) == 1
assert grades.usergrades[0].userid == 47
2 changes: 2 additions & 0 deletions tests/test_moodle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Auth,
Core,
Enrol,
GradeReport,
Mdl,
Mod,
Tool,
Expand All @@ -21,6 +22,7 @@ def test_moodle(moodle: Moodle):
assert isinstance(moodle.auth, Auth)
assert isinstance(moodle.core, Core)
assert isinstance(moodle.enrol, Enrol)
assert isinstance(moodle.grade_report, GradeReport)
assert isinstance(moodle.mod, Mod)
assert isinstance(moodle.tool, Tool)

Expand Down

0 comments on commit 8d98837

Please sign in to comment.