-
Notifications
You must be signed in to change notification settings - Fork 17
feat: add initial code to load a learning package #379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add initial code to load a learning package #379
Conversation
- Implement restore of the learning package - Add initial logic to handle ZIP file contents - Include placeholders for restoring other entities (containers, components, collections)
|
Thanks for the pull request, @dwong2708! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
|
Apologies for the delay. I'll review this on Tues. morning. |
ormsbee
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some relatively minor change requests. Thank you!
openedx_learning/apps/authoring/backup_restore/management/commands/lp_load.py
Outdated
Show resolved
Hide resolved
openedx_learning/apps/authoring/backup_restore/management/commands/lp_load.py
Outdated
Show resolved
Hide resolved
| # Public API | ||
| # -------------------------- | ||
|
|
||
| @transaction.atomic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This is okay for now, but we may need to be more granular with this eventually, instead of putting it over the entire method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood
| # -------------------------- | ||
|
|
||
| @transaction.atomic | ||
| def extract_zip(self, path: str) -> dict[str, Any]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- This function is meant to load these contents into the database, not just extract them from the zip file. So a function name like
loadseems more appropriate. - This will be easier to test if it takes a ZipFile as an argument, because then you'll be able to construct in-memory ZipFiles for testing purposes using BytesIO (instead of having a lot of temp files thrown around).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the point 2, what about to accept either a str or a ZipFile ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I applied the accept str or ZipFile approach. Please let me know if you are ok of that change. Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave this parameter as only a ZipFile and not either-or. Try to avoid overloading parameters like this when possible:
- It sometimes results in dependent optional parameters which can be confusing, e.g. "these optional params only apply when we pass a file path")
- It mixes concerns. There are more error scenarios with opening that file than what you have listed right now: permissions denied, invalid zip file (due to partial/broken upload), etc. Furthermore, the file loading is going to be different and potentially need to give different feedback depending on what's doing it -- it's the command prompt for a management command, but something different for an async celery task worker (where a /tmp file would be meaningless to the user).
Having the code to load the raw file and make sure it's the right-kind-of-thing is a discrete piece of logic that will likely grow more complex over time. For instance, maybe we'll want a custom loader where you point it to a directory tree, and it dynamically generates an in-memory ZipFile on the fly so that it's easier to browse and work with tests. If this class only takes a ZipFile as an init param, it's pretty clear that this custom loading logic should go outside this class. But if this init takes a string, then someone may look at that and think, "okay, well, if the string is a path to a zip file, do this, but if the string is a path to a directory tree, do this other thing...", further complicating things.
Overall, it just simplifies the logic of the class in the longer term if it assumes it gets a well-formed, readable zip file. Then this class can worry exclusively about the contents of the archive and whether they are consistent with each other, and not worry about lower-level I/O details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate your explanations — they definitely make sense. I’ve applied the changes.
| """ | ||
|
|
||
| def _load_component( | ||
| self, zipf: zipfile.ZipFile, component_file: str, learning_package: "LearningPackage" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: You can import LearningPackage from the publishing api.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. I also noticed the LearninPackage model is already imported. Thanks
Resolves: #380
Summary
This PR introduces the initial implementation for restoring a learning package from a ZIP archive. It sets the foundation for handling backup and restore of course-related data.
Changes
learning_package.tomlfileNotes
Next Steps