lms.model.scores
1import typing 2 3import edq.util.json 4import edq.util.time 5 6import lms.model.assignments 7import lms.model.base 8import lms.model.users 9 10class ScoreFragment(edq.util.json.DictConverter): 11 """ A small subset of information about a score. """ 12 13 def __init__(self, 14 score: typing.Union[float, None] = None, 15 comment: typing.Union[str, None] = None, 16 **kwargs: typing.Any) -> None: 17 self.score: typing.Union[float, None] = score 18 """ 19 The numeric score. 20 A None value indicates that the score should be cleared. 21 """ 22 23 self.comment: typing.Union[str, None] = comment 24 """ An optional comment for this score. """ 25 26class AssignmentScore(lms.model.base.BaseType): 27 """ 28 The score assignment to a student for an assignment (or scorable object). 29 """ 30 31 CORE_FIELDS = [ 32 'id', 'user', 'assignment', 'score', 'submission_date', 'graded_date', 'comment', 33 ] 34 35 def __init__(self, 36 id: typing.Union[str, None] = None, 37 score: typing.Union[float, None] = None, 38 submission_date: typing.Union[edq.util.time.Timestamp, None] = None, 39 graded_date: typing.Union[edq.util.time.Timestamp, None] = None, 40 comment: typing.Union[str, None] = None, 41 assignment: typing.Union[lms.model.assignments.AssignmentQuery, None] = None, 42 user: typing.Union[lms.model.users.UserQuery, None] = None, 43 **kwargs: typing.Any) -> None: 44 super().__init__(**kwargs) 45 46 self.id: typing.Union[str, None] = id 47 """ The LMS's identifier for this score. """ 48 49 self.assignment: typing.Union[lms.model.assignments.AssignmentQuery, None] = assignment 50 """ The assignment associated with this score. """ 51 52 self.user: typing.Union[lms.model.users.UserQuery, None] = user 53 """ The user associated with this score. """ 54 55 self.score: typing.Union[float, None] = score 56 """ The assignment score. """ 57 58 self.submission_date: typing.Union[edq.util.time.Timestamp, None] = submission_date 59 """ The datetime that the submission that received this score was submitted. """ 60 61 self.graded_date: typing.Union[edq.util.time.Timestamp, None] = graded_date 62 """ The datetime that the submission that received this score was graded. """ 63 64 self.comment: typing.Union[str, None] = comment 65 """ A comment attached to this score. """ 66 67 def to_fragment(self) -> ScoreFragment: 68 """ Get a score fragment from this assignment score. """ 69 70 return ScoreFragment(score = self.score, comment = self.comment) 71 72class Gradebook(lms.model.base.BaseType): 73 """ 74 A gradebook that contains scores for a set of users and assignments. 75 """ 76 77 CORE_FIELDS = [ 78 'assignments', 'users', '_entries', 79 ] 80 81 def __init__(self, 82 assignments: typing.List[lms.model.assignments.AssignmentQuery], 83 users: typing.List[lms.model.users.UserQuery], 84 **kwargs: typing.Any) -> None: 85 super().__init__(**kwargs) 86 87 self.assignments: typing.List[lms.model.assignments.AssignmentQuery] = assignments 88 """ The assignments represented in this gradebook. """ 89 90 self.users: typing.List[lms.model.users.UserQuery] = users 91 """ The users represented in this gradebook. """ 92 93 self._entries: typing.Dict[str, AssignmentScore] = {} 94 """ The scores held by this gradebook. """ 95 96 def _make_key(self, assignment_query: lms.model.assignments.AssignmentQuery, user_query: lms.model.users.UserQuery) -> str: 97 """ Create a key for this gradebook entry. """ 98 99 return f"{assignment_query.id}::{user_query.id}" 100 101 def get(self, 102 assignment_query: lms.model.assignments.AssignmentQuery, 103 user_query: lms.model.users.UserQuery, 104 ) -> typing.Union[AssignmentScore, None]: 105 """ Get the target gradebook entry. """ 106 107 found_assignment = None 108 for assignment in self.assignments: 109 if (assignment.match(assignment_query)): 110 found_assignment = assignment 111 break 112 113 if (found_assignment is None): 114 return None 115 116 found_user = None 117 for user in self.users: 118 if (user.match(user_query)): 119 found_user = user 120 break 121 122 if (found_user is None): 123 return None 124 125 return self._entries.get(self._make_key(found_assignment, found_user), None) 126 127 def get_scores_by_assignment(self, 128 ) -> typing.Dict[ 129 lms.model.assignments.AssignmentQuery, 130 typing.Dict[lms.model.users.UserQuery, AssignmentScore]]: 131 """ Get all entries indexed by assignment. """ 132 133 results: typing.Dict[ 134 lms.model.assignments.AssignmentQuery, 135 typing.Dict[lms.model.users.UserQuery, AssignmentScore]] = {} 136 137 for assignment in self.assignments: 138 results[assignment] = {} 139 140 for user in self.users: 141 key = self._make_key(assignment, user) 142 if (key not in self._entries): 143 continue 144 145 results[assignment][user] = self._entries[key] 146 147 return results 148 149 def add(self, score: AssignmentScore) -> None: 150 """ 151 Add the score to this gradebook. 152 If the user or assignment is not already in this gradebook, raise an exception. 153 154 The gradebook takes ownership of the score. 155 """ 156 157 found_assignment = None 158 for assignment in self.assignments: 159 if (assignment.match(score.assignment)): 160 found_assignment = assignment 161 break 162 163 if (found_assignment is None): 164 raise ValueError(f"Could not match gradebook assignment to score's assignment '{score.assignment}'.") 165 166 found_user = None 167 for user in self.users: 168 if (user.match(score.user)): 169 found_user = user 170 break 171 172 if (found_user is None): 173 raise ValueError(f"Could not match gradebook user to score's user '{score.user}'.") 174 175 # Update the score's queries. 176 score.assignment = found_assignment 177 score.user = found_user 178 179 self._entries[self._make_key(found_assignment, found_user)] = score 180 181 def update_queries(self, 182 assignment_queries: typing.List[lms.model.assignments.ResolvedAssignmentQuery], 183 user_queries: typing.List[lms.model.users.ResolvedUserQuery], 184 ) -> None: 185 """ Update any assignment/user queries with the supplied ones (matching on ID). """ 186 187 assignment_map = {query.id: query for query in assignment_queries} 188 user_map = {query.id: query for query in user_queries} 189 190 self.assignments = [assignment_map.get(assignment.id, assignment) for assignment in self.assignments] 191 self.users = [user_map.get(user.id, user) for user in self.users] 192 193 for score in self._entries.values(): 194 if (score.assignment is not None): 195 score.assignment = assignment_map.get(score.assignment.id, score.assignment) 196 197 if (score.user is not None): 198 score.user = user_map.get(score.user.id, score.user) 199 200 def as_text_rows(self, 201 skip_headers: bool = False, 202 pretty_headers: bool = False, 203 separator: str = ': ', 204 empty_value: str = '', 205 **kwargs: typing.Any) -> typing.List[str]: 206 rows: typing.List[str] = [] 207 for user in sorted(self.users): 208 # Add in a user separator. 209 if (len(rows) > 0): 210 rows.append('') 211 212 rows.append(f"User{separator}{user}") 213 214 for assignment in sorted(self.assignments): 215 score = self.get(assignment, user) 216 217 text = empty_value 218 if (score is not None): 219 text = str(score.score) 220 221 rows.append(f"{assignment}{separator}{text}") 222 223 return rows 224 225 def get_headers(self, 226 pretty_headers: bool = False, 227 **kwargs: typing.Any) -> typing.List[str]: 228 return ['User'] + [str(query) for query in sorted(self.assignments)] 229 230 def as_table_rows(self, 231 empty_value: str = '', 232 **kwargs: typing.Any) -> typing.List[typing.List[str]]: 233 rows = [] 234 for user in sorted(self.users): 235 row = [str(user)] 236 for assignment in sorted(self.assignments): 237 score = self.get(assignment, user) 238 239 text = empty_value 240 if (score is not None): 241 text = str(score.score) 242 243 row.append(text) 244 245 rows.append(row) 246 247 return rows 248 249 def as_json_dict(self, 250 include_extra_fields: bool = False, 251 **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: 252 """ 253 Get a dict representation of this object meant for display as JSON. 254 (Note that we are not returning JSON, just a dict that is ready to be converted to JSON.) 255 Calling this method differs from passing this object to json.dumps() (or any sibling), 256 because this method may not include all fields, may flatten or alter fields, and will order fields differently. 257 """ 258 259 scores = [] 260 for assignment in sorted(self.assignments): 261 row = [] 262 for user in sorted(self.users): 263 score: typing.Any = self.get(assignment, user) 264 if (score is not None): 265 score = score.as_json_dict(include_extra_fields = include_extra_fields, **kwargs) 266 267 row.append(score) 268 269 scores.append(row) 270 271 return { 272 'assignments': self.assignments, 273 'users': self.users, 274 'scores_assignment_user': scores, 275 } 276 277 def __len__(self) -> int: 278 return len(self._entries)
11class ScoreFragment(edq.util.json.DictConverter): 12 """ A small subset of information about a score. """ 13 14 def __init__(self, 15 score: typing.Union[float, None] = None, 16 comment: typing.Union[str, None] = None, 17 **kwargs: typing.Any) -> None: 18 self.score: typing.Union[float, None] = score 19 """ 20 The numeric score. 21 A None value indicates that the score should be cleared. 22 """ 23 24 self.comment: typing.Union[str, None] = comment 25 """ An optional comment for this score. """
A small subset of information about a score.
14 def __init__(self, 15 score: typing.Union[float, None] = None, 16 comment: typing.Union[str, None] = None, 17 **kwargs: typing.Any) -> None: 18 self.score: typing.Union[float, None] = score 19 """ 20 The numeric score. 21 A None value indicates that the score should be cleared. 22 """ 23 24 self.comment: typing.Union[str, None] = comment 25 """ An optional comment for this score. """
27class AssignmentScore(lms.model.base.BaseType): 28 """ 29 The score assignment to a student for an assignment (or scorable object). 30 """ 31 32 CORE_FIELDS = [ 33 'id', 'user', 'assignment', 'score', 'submission_date', 'graded_date', 'comment', 34 ] 35 36 def __init__(self, 37 id: typing.Union[str, None] = None, 38 score: typing.Union[float, None] = None, 39 submission_date: typing.Union[edq.util.time.Timestamp, None] = None, 40 graded_date: typing.Union[edq.util.time.Timestamp, None] = None, 41 comment: typing.Union[str, None] = None, 42 assignment: typing.Union[lms.model.assignments.AssignmentQuery, None] = None, 43 user: typing.Union[lms.model.users.UserQuery, None] = None, 44 **kwargs: typing.Any) -> None: 45 super().__init__(**kwargs) 46 47 self.id: typing.Union[str, None] = id 48 """ The LMS's identifier for this score. """ 49 50 self.assignment: typing.Union[lms.model.assignments.AssignmentQuery, None] = assignment 51 """ The assignment associated with this score. """ 52 53 self.user: typing.Union[lms.model.users.UserQuery, None] = user 54 """ The user associated with this score. """ 55 56 self.score: typing.Union[float, None] = score 57 """ The assignment score. """ 58 59 self.submission_date: typing.Union[edq.util.time.Timestamp, None] = submission_date 60 """ The datetime that the submission that received this score was submitted. """ 61 62 self.graded_date: typing.Union[edq.util.time.Timestamp, None] = graded_date 63 """ The datetime that the submission that received this score was graded. """ 64 65 self.comment: typing.Union[str, None] = comment 66 """ A comment attached to this score. """ 67 68 def to_fragment(self) -> ScoreFragment: 69 """ Get a score fragment from this assignment score. """ 70 71 return ScoreFragment(score = self.score, comment = self.comment)
The score assignment to a student for an assignment (or scorable object).
36 def __init__(self, 37 id: typing.Union[str, None] = None, 38 score: typing.Union[float, None] = None, 39 submission_date: typing.Union[edq.util.time.Timestamp, None] = None, 40 graded_date: typing.Union[edq.util.time.Timestamp, None] = None, 41 comment: typing.Union[str, None] = None, 42 assignment: typing.Union[lms.model.assignments.AssignmentQuery, None] = None, 43 user: typing.Union[lms.model.users.UserQuery, None] = None, 44 **kwargs: typing.Any) -> None: 45 super().__init__(**kwargs) 46 47 self.id: typing.Union[str, None] = id 48 """ The LMS's identifier for this score. """ 49 50 self.assignment: typing.Union[lms.model.assignments.AssignmentQuery, None] = assignment 51 """ The assignment associated with this score. """ 52 53 self.user: typing.Union[lms.model.users.UserQuery, None] = user 54 """ The user associated with this score. """ 55 56 self.score: typing.Union[float, None] = score 57 """ The assignment score. """ 58 59 self.submission_date: typing.Union[edq.util.time.Timestamp, None] = submission_date 60 """ The datetime that the submission that received this score was submitted. """ 61 62 self.graded_date: typing.Union[edq.util.time.Timestamp, None] = graded_date 63 """ The datetime that the submission that received this score was graded. """ 64 65 self.comment: typing.Union[str, None] = comment 66 """ A comment attached to this score. """
The common fields shared across backends for this type that are used for comparison and other operations. Child classes should set this to define how comparisons are made.
The assignment associated with this score.
The datetime that the submission that received this score was submitted.
The datetime that the submission that received this score was graded.
73class Gradebook(lms.model.base.BaseType): 74 """ 75 A gradebook that contains scores for a set of users and assignments. 76 """ 77 78 CORE_FIELDS = [ 79 'assignments', 'users', '_entries', 80 ] 81 82 def __init__(self, 83 assignments: typing.List[lms.model.assignments.AssignmentQuery], 84 users: typing.List[lms.model.users.UserQuery], 85 **kwargs: typing.Any) -> None: 86 super().__init__(**kwargs) 87 88 self.assignments: typing.List[lms.model.assignments.AssignmentQuery] = assignments 89 """ The assignments represented in this gradebook. """ 90 91 self.users: typing.List[lms.model.users.UserQuery] = users 92 """ The users represented in this gradebook. """ 93 94 self._entries: typing.Dict[str, AssignmentScore] = {} 95 """ The scores held by this gradebook. """ 96 97 def _make_key(self, assignment_query: lms.model.assignments.AssignmentQuery, user_query: lms.model.users.UserQuery) -> str: 98 """ Create a key for this gradebook entry. """ 99 100 return f"{assignment_query.id}::{user_query.id}" 101 102 def get(self, 103 assignment_query: lms.model.assignments.AssignmentQuery, 104 user_query: lms.model.users.UserQuery, 105 ) -> typing.Union[AssignmentScore, None]: 106 """ Get the target gradebook entry. """ 107 108 found_assignment = None 109 for assignment in self.assignments: 110 if (assignment.match(assignment_query)): 111 found_assignment = assignment 112 break 113 114 if (found_assignment is None): 115 return None 116 117 found_user = None 118 for user in self.users: 119 if (user.match(user_query)): 120 found_user = user 121 break 122 123 if (found_user is None): 124 return None 125 126 return self._entries.get(self._make_key(found_assignment, found_user), None) 127 128 def get_scores_by_assignment(self, 129 ) -> typing.Dict[ 130 lms.model.assignments.AssignmentQuery, 131 typing.Dict[lms.model.users.UserQuery, AssignmentScore]]: 132 """ Get all entries indexed by assignment. """ 133 134 results: typing.Dict[ 135 lms.model.assignments.AssignmentQuery, 136 typing.Dict[lms.model.users.UserQuery, AssignmentScore]] = {} 137 138 for assignment in self.assignments: 139 results[assignment] = {} 140 141 for user in self.users: 142 key = self._make_key(assignment, user) 143 if (key not in self._entries): 144 continue 145 146 results[assignment][user] = self._entries[key] 147 148 return results 149 150 def add(self, score: AssignmentScore) -> None: 151 """ 152 Add the score to this gradebook. 153 If the user or assignment is not already in this gradebook, raise an exception. 154 155 The gradebook takes ownership of the score. 156 """ 157 158 found_assignment = None 159 for assignment in self.assignments: 160 if (assignment.match(score.assignment)): 161 found_assignment = assignment 162 break 163 164 if (found_assignment is None): 165 raise ValueError(f"Could not match gradebook assignment to score's assignment '{score.assignment}'.") 166 167 found_user = None 168 for user in self.users: 169 if (user.match(score.user)): 170 found_user = user 171 break 172 173 if (found_user is None): 174 raise ValueError(f"Could not match gradebook user to score's user '{score.user}'.") 175 176 # Update the score's queries. 177 score.assignment = found_assignment 178 score.user = found_user 179 180 self._entries[self._make_key(found_assignment, found_user)] = score 181 182 def update_queries(self, 183 assignment_queries: typing.List[lms.model.assignments.ResolvedAssignmentQuery], 184 user_queries: typing.List[lms.model.users.ResolvedUserQuery], 185 ) -> None: 186 """ Update any assignment/user queries with the supplied ones (matching on ID). """ 187 188 assignment_map = {query.id: query for query in assignment_queries} 189 user_map = {query.id: query for query in user_queries} 190 191 self.assignments = [assignment_map.get(assignment.id, assignment) for assignment in self.assignments] 192 self.users = [user_map.get(user.id, user) for user in self.users] 193 194 for score in self._entries.values(): 195 if (score.assignment is not None): 196 score.assignment = assignment_map.get(score.assignment.id, score.assignment) 197 198 if (score.user is not None): 199 score.user = user_map.get(score.user.id, score.user) 200 201 def as_text_rows(self, 202 skip_headers: bool = False, 203 pretty_headers: bool = False, 204 separator: str = ': ', 205 empty_value: str = '', 206 **kwargs: typing.Any) -> typing.List[str]: 207 rows: typing.List[str] = [] 208 for user in sorted(self.users): 209 # Add in a user separator. 210 if (len(rows) > 0): 211 rows.append('') 212 213 rows.append(f"User{separator}{user}") 214 215 for assignment in sorted(self.assignments): 216 score = self.get(assignment, user) 217 218 text = empty_value 219 if (score is not None): 220 text = str(score.score) 221 222 rows.append(f"{assignment}{separator}{text}") 223 224 return rows 225 226 def get_headers(self, 227 pretty_headers: bool = False, 228 **kwargs: typing.Any) -> typing.List[str]: 229 return ['User'] + [str(query) for query in sorted(self.assignments)] 230 231 def as_table_rows(self, 232 empty_value: str = '', 233 **kwargs: typing.Any) -> typing.List[typing.List[str]]: 234 rows = [] 235 for user in sorted(self.users): 236 row = [str(user)] 237 for assignment in sorted(self.assignments): 238 score = self.get(assignment, user) 239 240 text = empty_value 241 if (score is not None): 242 text = str(score.score) 243 244 row.append(text) 245 246 rows.append(row) 247 248 return rows 249 250 def as_json_dict(self, 251 include_extra_fields: bool = False, 252 **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: 253 """ 254 Get a dict representation of this object meant for display as JSON. 255 (Note that we are not returning JSON, just a dict that is ready to be converted to JSON.) 256 Calling this method differs from passing this object to json.dumps() (or any sibling), 257 because this method may not include all fields, may flatten or alter fields, and will order fields differently. 258 """ 259 260 scores = [] 261 for assignment in sorted(self.assignments): 262 row = [] 263 for user in sorted(self.users): 264 score: typing.Any = self.get(assignment, user) 265 if (score is not None): 266 score = score.as_json_dict(include_extra_fields = include_extra_fields, **kwargs) 267 268 row.append(score) 269 270 scores.append(row) 271 272 return { 273 'assignments': self.assignments, 274 'users': self.users, 275 'scores_assignment_user': scores, 276 } 277 278 def __len__(self) -> int: 279 return len(self._entries)
A gradebook that contains scores for a set of users and assignments.
82 def __init__(self, 83 assignments: typing.List[lms.model.assignments.AssignmentQuery], 84 users: typing.List[lms.model.users.UserQuery], 85 **kwargs: typing.Any) -> None: 86 super().__init__(**kwargs) 87 88 self.assignments: typing.List[lms.model.assignments.AssignmentQuery] = assignments 89 """ The assignments represented in this gradebook. """ 90 91 self.users: typing.List[lms.model.users.UserQuery] = users 92 """ The users represented in this gradebook. """ 93 94 self._entries: typing.Dict[str, AssignmentScore] = {} 95 """ The scores held by this gradebook. """
The common fields shared across backends for this type that are used for comparison and other operations. Child classes should set this to define how comparisons are made.
The assignments represented in this gradebook.
102 def get(self, 103 assignment_query: lms.model.assignments.AssignmentQuery, 104 user_query: lms.model.users.UserQuery, 105 ) -> typing.Union[AssignmentScore, None]: 106 """ Get the target gradebook entry. """ 107 108 found_assignment = None 109 for assignment in self.assignments: 110 if (assignment.match(assignment_query)): 111 found_assignment = assignment 112 break 113 114 if (found_assignment is None): 115 return None 116 117 found_user = None 118 for user in self.users: 119 if (user.match(user_query)): 120 found_user = user 121 break 122 123 if (found_user is None): 124 return None 125 126 return self._entries.get(self._make_key(found_assignment, found_user), None)
Get the target gradebook entry.
128 def get_scores_by_assignment(self, 129 ) -> typing.Dict[ 130 lms.model.assignments.AssignmentQuery, 131 typing.Dict[lms.model.users.UserQuery, AssignmentScore]]: 132 """ Get all entries indexed by assignment. """ 133 134 results: typing.Dict[ 135 lms.model.assignments.AssignmentQuery, 136 typing.Dict[lms.model.users.UserQuery, AssignmentScore]] = {} 137 138 for assignment in self.assignments: 139 results[assignment] = {} 140 141 for user in self.users: 142 key = self._make_key(assignment, user) 143 if (key not in self._entries): 144 continue 145 146 results[assignment][user] = self._entries[key] 147 148 return results
Get all entries indexed by assignment.
150 def add(self, score: AssignmentScore) -> None: 151 """ 152 Add the score to this gradebook. 153 If the user or assignment is not already in this gradebook, raise an exception. 154 155 The gradebook takes ownership of the score. 156 """ 157 158 found_assignment = None 159 for assignment in self.assignments: 160 if (assignment.match(score.assignment)): 161 found_assignment = assignment 162 break 163 164 if (found_assignment is None): 165 raise ValueError(f"Could not match gradebook assignment to score's assignment '{score.assignment}'.") 166 167 found_user = None 168 for user in self.users: 169 if (user.match(score.user)): 170 found_user = user 171 break 172 173 if (found_user is None): 174 raise ValueError(f"Could not match gradebook user to score's user '{score.user}'.") 175 176 # Update the score's queries. 177 score.assignment = found_assignment 178 score.user = found_user 179 180 self._entries[self._make_key(found_assignment, found_user)] = score
Add the score to this gradebook. If the user or assignment is not already in this gradebook, raise an exception.
The gradebook takes ownership of the score.
182 def update_queries(self, 183 assignment_queries: typing.List[lms.model.assignments.ResolvedAssignmentQuery], 184 user_queries: typing.List[lms.model.users.ResolvedUserQuery], 185 ) -> None: 186 """ Update any assignment/user queries with the supplied ones (matching on ID). """ 187 188 assignment_map = {query.id: query for query in assignment_queries} 189 user_map = {query.id: query for query in user_queries} 190 191 self.assignments = [assignment_map.get(assignment.id, assignment) for assignment in self.assignments] 192 self.users = [user_map.get(user.id, user) for user in self.users] 193 194 for score in self._entries.values(): 195 if (score.assignment is not None): 196 score.assignment = assignment_map.get(score.assignment.id, score.assignment) 197 198 if (score.user is not None): 199 score.user = user_map.get(score.user.id, score.user)
Update any assignment/user queries with the supplied ones (matching on ID).
201 def as_text_rows(self, 202 skip_headers: bool = False, 203 pretty_headers: bool = False, 204 separator: str = ': ', 205 empty_value: str = '', 206 **kwargs: typing.Any) -> typing.List[str]: 207 rows: typing.List[str] = [] 208 for user in sorted(self.users): 209 # Add in a user separator. 210 if (len(rows) > 0): 211 rows.append('') 212 213 rows.append(f"User{separator}{user}") 214 215 for assignment in sorted(self.assignments): 216 score = self.get(assignment, user) 217 218 text = empty_value 219 if (score is not None): 220 text = str(score.score) 221 222 rows.append(f"{assignment}{separator}{text}") 223 224 return rows
Create a representation of this object in the "text" style of this project meant for display. A list of rows will be returned.
226 def get_headers(self, 227 pretty_headers: bool = False, 228 **kwargs: typing.Any) -> typing.List[str]: 229 return ['User'] + [str(query) for query in sorted(self.assignments)]
Get a list of headers to label the values represented by this object meant for display. This method is a companion to as_table_rows(), given the same options these two methods will produce rows with the same length and ordering.
231 def as_table_rows(self, 232 empty_value: str = '', 233 **kwargs: typing.Any) -> typing.List[typing.List[str]]: 234 rows = [] 235 for user in sorted(self.users): 236 row = [str(user)] 237 for assignment in sorted(self.assignments): 238 score = self.get(assignment, user) 239 240 text = empty_value 241 if (score is not None): 242 text = str(score.score) 243 244 row.append(text) 245 246 rows.append(row) 247 248 return rows
Get a list of the values by this object meant for display. This method is a companion to get_headers(), given the same options these two methods will produce rows with the same length and ordering.
Note that the default implementation for this method always return a single row, but children may override and return multiple rows per object.
250 def as_json_dict(self, 251 include_extra_fields: bool = False, 252 **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: 253 """ 254 Get a dict representation of this object meant for display as JSON. 255 (Note that we are not returning JSON, just a dict that is ready to be converted to JSON.) 256 Calling this method differs from passing this object to json.dumps() (or any sibling), 257 because this method may not include all fields, may flatten or alter fields, and will order fields differently. 258 """ 259 260 scores = [] 261 for assignment in sorted(self.assignments): 262 row = [] 263 for user in sorted(self.users): 264 score: typing.Any = self.get(assignment, user) 265 if (score is not None): 266 score = score.as_json_dict(include_extra_fields = include_extra_fields, **kwargs) 267 268 row.append(score) 269 270 scores.append(row) 271 272 return { 273 'assignments': self.assignments, 274 'users': self.users, 275 'scores_assignment_user': scores, 276 }
Get a dict representation of this object meant for display as JSON. (Note that we are not returning JSON, just a dict that is ready to be converted to JSON.) Calling this method differs from passing this object to json.dumps() (or any sibling), because this method may not include all fields, may flatten or alter fields, and will order fields differently.