-
Notifications
You must be signed in to change notification settings - Fork 4.1k
[BD-13] [BB-5363] refactor: deprecates replace url related properties from ModuleSystem #29880
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
[BD-13] [BB-5363] refactor: deprecates replace url related properties from ModuleSystem #29880
Conversation
Thanks for the pull request, @kaustavb12! I've created BLENDED-1088 to keep track of it in Jira. More details are on the BD-13 project page. When this pull request is ready, tag your edX technical lead. |
a37f47d
to
8a7baa2
Compare
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.
@kaustavb12, could you please add testing instructions and prepare the sandbox?
hint_text=HTML(self.runtime.service(self, "replace_urls").replace_urls( | ||
get_inner_html_from_xpath(demand_hints[counter]), | ||
static_replace_only=True | ||
)) |
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.
Is it the only place where static_replace_only
is used? If yes, does it really make sense to keep it? Not replacing course links in the hints is an inconsistent behavior, as these links are replaced in answers.
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.
static_replace_url
is also used in studio preview
I introduced this argument, only to keep the logic consistent in these two places before and after this PR, where only the static urls were being replaced and not the course or jump-to-id urls.
In case of hints, I think replacing course or jump-to-id urls in the hints section could be useful in a scenario where the course author may want to provide a link to a portion of a course content in the assessment hints. Accordingly I have removed static_replace_only=True
from here.
In the case of studio preview, I am not sure about the reasoning behind not replacing course urls (not replacing jump-to-id url make sense as the course is dynamic in the studio and the ids may change). Do you think, we should replace the course urls here as well ? In that case we can get rid of the static_replace_url
argument.
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.
static_replace_url is also used in studio preview
Ah, that's right.
Do you think, we should replace the course urls here as well ? In that case we can get rid of the static_replace_url argument.
Right now Studio is just providing the {STUDIO_URL}/course/about
URL. After this change, it would be pointing to {STUDIO_URL}/courses/{COURSE_ID/about
. These pages do not exist in Studio anyway, so this won't make a too big difference. Let's leave it as-is, for consistency with the existing approach.
not replacing jump-to-id url make sense as the course is dynamic in the studio and the ids may change
It could be nice to be able to check within Studio that the ID is correct by navigating there. However, the implementation would probably need to change for the Studio preview (the URLs are different), so let's omit this.
from common.djangoapps.static_replace import replace_course_urls, replace_jump_to_id_urls, replace_static_urls | ||
|
||
|
||
class ReplaceURLService(Service): |
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.
Given that we're adding this service, should we also deprecate these methods?
cc: @bradenmacdonald, as I'm not sure if these aren't used by the blockstore.
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.
They're not called by blockstore but they are called by XBlocks, so yes.
@kaustavb12 Please make the same changes to
edx-platform/openedx/core/djangoapps/xblock/runtime/shims.py
Lines 179 to 219 in 25b275b
def replace_urls(self, html_str): | |
""" | |
Deprecated precursor to transform_static_paths_to_urls | |
Given an HTML string, replace any static file paths like | |
/static/foo.png | |
(which are really pointing to block-specific assets stored in blockstore) | |
with working absolute URLs like | |
https://s3.example.com/blockstore/bundle17/this-block/assets/324.png | |
See common/djangoapps/static_replace/__init__.py | |
This is generally done automatically for the HTML rendered by XBlocks, | |
but if an XBlock wants to have correct URLs in data returned by its | |
handlers, the XBlock must call this API directly. | |
Note that the paths are only replaced if they are in "quotes" such as if | |
they are an HTML attribute or JSON data value. Thus, to transform only a | |
single path string on its own, you must pass html_str=f'"{path}"' | |
""" | |
return self.transform_static_paths_to_urls(self._active_block, html_str) | |
def replace_course_urls(self, html_str): | |
""" | |
Given an HTML string, replace any course-relative URLs like | |
/course/blah | |
with working URLs like | |
/course/:course_id/blah | |
See common/djangoapps/static_replace/__init__.py | |
""" | |
# TODO: implement or deprecate. | |
# See also the version in openedx/core/lib/xblock_utils/__init__.py | |
return html_str | |
def replace_jump_to_id_urls(self, html_str): | |
""" | |
Replace /jump_to_id/ URLs in the HTML with expanded versions. | |
See common/djangoapps/static_replace/__init__.py | |
""" | |
# TODO: implement or deprecate. | |
# See also the version in openedx/core/lib/xblock_utils/__init__.py | |
return html_str |
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.
These methods are part of the RuntimeShim class which is used with the XBlockRuntime class.
The XBlockRuntime class is a super class of the BlockstoreXBlockRuntime class
As I understand, blockstore Xblocks are not attached to courses, and so they don't have course id associated with them.
In that case would having replace_course_urls() and replace_jump_to_id_urls() methods in this shim necessary, since replacing both course urls and jump-to-id urls makes use of course ids.
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.
As I understand, blockstore Xblocks are not attached to courses, and so they don't have course id associated with them.
That's true, and replace_course_urls
is not needed for that reason. (At least not yet; blockstore will support courses in the future!)
But: blockstore XBlocks still use static files and they still need to have their /static/...
asset paths rewritten. The difference is that in Blockstore, static assets are stored with the XBlock not with the course.
I actually created a new API for this, self.runtime.transform_static_paths_to_urls
:
edx-platform/openedx/core/djangoapps/xblock/runtime/runtime.py
Lines 338 to 354 in 4f58ed4
def transform_static_paths_to_urls(self, block, html_str): | |
""" | |
Given an HTML string, replace any static file paths like | |
/static/foo.png | |
(which are really pointing to block-specific assets stored in blockstore) | |
with working absolute URLs like | |
https://s3.example.com/blockstore/bundle17/this-block/assets/324.png | |
See common/djangoapps/static_replace/__init__.py | |
This is generally done automatically for the HTML rendered by XBlocks, | |
but if an XBlock wants to have correct URLs in data returned by its | |
handlers, the XBlock must call this API directly. | |
Note that the paths are only replaced if they are in "quotes" such as if | |
they are an HTML attribute or JSON data value. Thus, to transform only a | |
single path string on its own, you must pass html_str=f'"{path}"' | |
""" |
And if you look at shims.py
, you can see that the old APIs are just wrappers around the new API.
So, if you want this service to be the new API, you'll have to implement it for the blockstore runtime as well, and make sure that when it's called in the blockstore runtime it uses self.runtime.transform_static_paths_to_urls
to do the rewriting, which will correctly rewrite the URLs to refer to assets from the XBlock's "bundle".
The easiest way to see what I'm talking about would be to set up blockstore yourself, e.g. following these instructions and then create within blockstore an HTML block, and upload an image to the HTML block, then set the image src to /static/image.png
and make sure it's working.
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.
Let me know if you want more help!
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.
@bradenmacdonald, I'm copying the message from @kaustavb12 here.
I have used the ReplaceURLService directly here instead of adding the service in the service() method. This is because, for invoking the service from this method we need to add a declaration for each Xblock in the form of @XBlock.needs('mako'). However, I couldn't figure out the correct classes for xblocks like Completion, Drag and Drop, Feedback, Survey, etc.
If you think the correct implementation should have been through the service() method, then I will look into in further later in the sprint.
As I don't know what this change means for blockstore, I could use a second pair of eyes to check the approach from c1c323ce08ac200955e921798039a014688bb264 when you have a moment. For now, we don't need to use the attributes of ReplaceURLService here, so we could make ReplaceURLService.replace_block_urls
a static method to start using it as an API. If we are going to support courses with blockstore in the future, then we could expand the service to support them, and merge replace_static_block_urls
with replace_static_urls
within static_replace/__init__.py
. Would it make sense?
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.
@Agrendalath Sure, I left my comments on c1c323ce08ac200955e921798039a014688bb264
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.
@bradenmacdonald
Thanks a lot pointing me to the instructions to setup blockstore in devstack and for reviewing the changes. It really helped me gain a lot of context about xblocks and the blockstore runtime.
I have now incorporated all your suggestions, and now there is only one API in ReplaceURLService which can be called by XBlocks as needed in the form of self.runtime.service(self, 'replace_urls').replace_urls(text)
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.
Also I have gone ahead and merged the new replace_static_block_urls
function with the replace_static_urls
function in static_replace/init.py similar to what was done for ReplaceURLService to avoid code duplication
cc. @Agrendalath
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.
Thanks @kaustavb12, those changes look great :)
dda52d2
to
e5c75ae
Compare
e727391
to
8fb0a90
Compare
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 tested this: tested that replacing URLs in XBlocks works correctly with the new service
- I read through the code
- I checked for accessibility issues: n/a
- Includes documentation: n/a
- I made sure any change in configuration variables is reflected in the corresponding client's
configuration-secure
repository: n/a
@ormsbee, would you like to take a look before we merge this? |
@Agrendalath: As long as it has @bradenmacdonald's blessing, I'm fine with not reviewing it. Please arrange the timing of the merge with @jristau1984, @connorhaugh, or @doctoryes though–probably for Monday or Tuesday? In general, these deep-in-the-modulestore changes have a higher risk of introducing regressions with the wide array of interesting content data that edX has in its catalog. |
Deprecates the following attributes from ModuleSystem: * replace_urls * replace_course_urls * replace_jump_to_id_urls A new ReplaceURLService is created as replacement with a unified replace_urls method
8fb0a90
to
cfdf6c7
Compare
@kaustavb12 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
EdX Release Notice: This PR has been deployed to the staging environment in preparation for a release to production. |
EdX Release Notice: This PR has been deployed to the production environment. |
`ReplaceURLService` replaced deprecated runtime methods in Nutmeg: openedx/edx-platform#29880
Description
Builds on the shim added by #29190 to deprecate the following
ModuleSystem
attributes in favour of the added ReplaceURLService:replace_urls
,replace_course_urls
,replace_jump_to_id_urls
This change should not affect any user of edx-platform
Supporting information
Testing instructions
LMS: https://pr29880.sandbox.opencraft.hosting/
Studio: https://studio.pr29880.sandbox.opencraft.hosting/
Studio:
Section1
>SubsectionA
> HTMLLMS:
Hint
Mobile API: