Feat: Added persistance to the cl#13
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements data persistence for the student management CLI application, allowing assignments and grades to be saved and loaded from a JSON file.
Key Changes:
- Added custom JSON encoder/decoder classes to handle datetime serialization
- Implemented save/load functionality in StudentManager with error handling for missing or corrupted files
- Integrated persistence into the main application flow to automatically load on startup and save on exit
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
| utils.py | Added DateTimeEncoder/DateTimeDecoder classes for datetime serialization and enhanced error handling in load_from_json |
| student_manager.py | Added persistence methods (dump_manager, load_manager) and serialization helpers (__ser_object, __deser_object) |
| main.py | Integrated data loading on startup and saving on exit with error handling for corrupted files |
| .gitignore | Added blank line (formatting change) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
17f5ccc to
e41a4f2
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return { | ||
| "status": 1 | ||
| } | ||
| except json.JSONDecodeError as e: | ||
| os.remove(filename) | ||
| return { | ||
| "status": 2 | ||
| } |
There was a problem hiding this comment.
The return value structure is inconsistent. When successful, the function returns the actual data dictionary, but on error it returns a status dictionary with a "status" key. This makes it difficult for callers to distinguish between actual data that might contain a "status" key and error conditions. Consider using a more explicit pattern like returning a tuple (data, status) or raising exceptions for error cases.
utils.py
Outdated
| """Handles special case of date deserialization""" | ||
| for key, value in obj.items(): | ||
| if isinstance(value, str): | ||
| try: | ||
| obj[key] = datetime.fromisoformat(value) | ||
| except ValueError: | ||
| pass # Not a datetime string | ||
| return obj | ||
|
|
There was a problem hiding this comment.
The object_hook method iterates over dictionary items and attempts to modify the dictionary during iteration, which can work but only handles top-level datetime strings. Nested dictionaries or lists containing datetime strings won't be properly converted. Additionally, this approach will attempt to parse every string value as a datetime, which could be inefficient for large objects with many string fields.
| """Handles special case of date deserialization""" | |
| for key, value in obj.items(): | |
| if isinstance(value, str): | |
| try: | |
| obj[key] = datetime.fromisoformat(value) | |
| except ValueError: | |
| pass # Not a datetime string | |
| return obj | |
| """Handles special case of date deserialization, including nested structures""" | |
| return self._decode_dates(obj) | |
| def _decode_dates(self, value): | |
| if isinstance(value, dict): | |
| return {k: self._decode_dates(v) for k, v in value.items()} | |
| elif isinstance(value, list): | |
| return [self._decode_dates(item) for item in value] | |
| elif isinstance(value, str): | |
| try: | |
| return datetime.fromisoformat(value) | |
| except ValueError: | |
| return value | |
| else: | |
| return value |
student_manager.py
Outdated
| if "status" in data: | ||
| status = data.get("status") | ||
| return cls(), status | ||
| return cls.__deser_object(data), 0 |
There was a problem hiding this comment.
Missing cls parameter in the call to __deser_object. Should be cls._StudentManager__deser_object(data) due to name mangling, or better yet, change the method to use single underscore as noted in another comment.
student_manager.py
Outdated
| def dump_manager(self): | ||
| """Dumps data into json file for persistence""" | ||
| data = self.__ser_object() | ||
| save_to_json(data, self.persistence_FILE_NAME) |
There was a problem hiding this comment.
Typo in method name: persistence_FILE_NAME should be PERSISTENCE_FILE_NAME to match the constant defined at line 10.
| save_to_json(data, self.persistence_FILE_NAME) | |
| save_to_json(data, self.PERSISTENCE_FILE_NAME) |
|
|
||
| def __ser_object(self): | ||
| """ | ||
| Protected method to aggrigate data |
There was a problem hiding this comment.
Typo in comment: aggrigate should be aggregate.
| Protected method to aggrigate data | |
| Protected method to aggregate data |
|
fix these, rest lgtm! |
|
Also do squash your commits into one with a better commit message, Thanks! |
6edbb11 to
e0fc1f0
Compare
|
Resolve the conflict with the main, i.e. rebase it to upstream. Also mark the conversation resolved if you are done with that. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
utils.py:1
- Corrected spelling of 'aggrigate' to 'aggregate'.
"""
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
bb3a203 to
81eecfa
Compare
|
Lgtm thanks! |
Data persistence has been implemented with all the requirements.