-
Notifications
You must be signed in to change notification settings - Fork 2
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
Python upgrade from 3.9.x to 3.12.x #3089
Conversation
4450d42
to
39b5a3d
Compare
5d5b638
to
1bef9fa
Compare
1bef9fa
to
1f40793
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 requested a couple of changes and some questions. Some change requests would need to be applied overall as I didn't add a separate comment for each of them.
Also, My perception was that we will be doing Webpack upgrade as part of https://github.com/mitodl/hq/issues/5077 separately but this PR contains the code for that as well.
@@ -30,7 +30,7 @@ def process_exception(self, request, exception): | |||
url = self.get_redirect_uri(request, exception) | |||
|
|||
if url: # noqa: RET503 | |||
url += ("?" in url and "&" or "?") + "message={0}&backend={1}".format( # noqa: UP030, UP032 | |||
url += ("?" in url and "&" or "?") + "message={}&backend={}".format( # noqa: UP032 |
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.
We can even replace it with f-string
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.
The reason pyupgrade
did not convert this into an f-string is likely due to its design choice to prioritize readability. According to the pyupgrade documentation, it intentionally avoids converting expressions into f-strings
if doing so would make the expression longer or if the substitution parameters are sufficiently complicated, as this can decrease readability.
In this case, the expression might have been considered sufficiently complex, or the transformation into an f-string might have made it less readable, which is why pyupgrade retained the .format() syntax.
However, if you believe an f-string would improve clarity in this case, I'm open to making the change manually. What do you think?
This holds true for similar comments you mentioned regarding f-string
where pyupgrade
intentionally avoids converting expressions into f-strings
.
@@ -57,7 +57,7 @@ def get_user_enrollments(user): | |||
for program_enrollment in program_enrollments | |||
) | |||
) | |||
program_course_ids = set(course.id for course in program_courses) # noqa: C401 |
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 think the set might have been intentional here for unique values.
@@ -33,14 +33,14 @@ def mock_cybersource_wsdl(mocked_responses, settings, service_version=SERVICE_VE | |||
Mocks the responses to achieve a functional WSDL | |||
""" | |||
# in order for zeep to load the wsdl, it will load the wsdl and the accompanying xsd definitions | |||
with open(f"{DATA_DIR}/CyberSourceTransaction_{service_version}.wsdl", "r") as wsdl: # noqa: PTH123, UP015 | |||
with open(f"{DATA_DIR}/CyberSourceTransaction_{service_version}.wsdl") as wsdl: # noqa: PTH123 |
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.
The file open is readable by default but explicitly adding "r"
adds more readability for all code readers. Did Python upgrade complain about it? Same goes for the line below.
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.
It does not complain but the open()
function in Python defaults to read mode ("r"), which pyupgrade
makes explicitly specifying "r" to redundant-open-mode/unnecessary and removes it. So we can go any of the following options:
- Keep the Explicit "r"
- We can keep the explicit "r" for readability if that's preferred. Although
pyupgrade
removed it because it's not necessary, adding it back can make the intent clearer to all code readers, especially those who may not be aware of the default behavior.
- We can keep the explicit "r" for readability if that's preferred. Although
- Adopt Python's Default Behavior
- We can follow Python's default behavior to avoid redundant open mode. It resolves redundant-open-modes (UP015 - derived from the pyupgrade) which recommends removing unnecessary open modes to reduce confusion.
Note: The first option will be applied consistently to all instances where this change is present and/or explicitly mentioned.
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 for the details you answered my question but maybe inverted, below is why.
It does not complain but the open() function in Python defaults to read mode ("r"), which pyupgrade makes explicitly specifying "r" to redundant-open-mode/unnecessary and removes it. So we can go any of the following options:
I think if pyupgrade complains about it that should mean that the python upgrade does complain. In, which case maybe we can remove the r
and add a code comment above this line saying that the file open is read-only by default.
courses/serializers_test.py
Outdated
@@ -6,6 +6,7 @@ | |||
|
|||
import factory | |||
import pytest | |||
import pytz |
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.
We intentionally moved away from pytz
as part of #2867. Official docs on https://docs.djangoproject.com/en/5.0/releases/4.0/#what-s-new-in-django-4-0
@@ -283,13 +283,11 @@ def test_course_view( # noqa: PLR0913 | |||
class_name = "enrolled" | |||
|
|||
assert ( | |||
f'<a class="enroll-button {class_name}" href="{url}">'.encode("utf-8") # noqa: UP012 | |||
in resp.content | |||
f'<a class="enroll-button {class_name}" href="{url}">'.encode() in resp.content |
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.
Same thing here, Does python upgrade complain about it? explicitly adding utf-8
makes it more readable. Same for the places below.
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 change is also made by pyupgrade
to encode string to bytes literal as UTF-8 is the default encoding in Python 3. This resolves unnecessary-encode-utf8 (UP012))
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.
My answer to this would be similar to #3089 (comment)
mitxpro/templates/base.html
Outdated
@@ -32,8 +32,6 @@ | |||
{% endif %} | |||
</script> | |||
{% render_bundle 'style' %} | |||
{% render_bundle 'common' %} |
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 this needed? Or maybe this is part of Webpack upgrade, If so, we should remove it from this PR.
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.
The changes you mentioned here, along with others related to Webpack are part of the Webpack upgrade. We should first review this PR before proceeding with the Python upgrade, as it depends on the Webpack upgrade and will need to be rebased afterward. For more details, refer to this comment #3089 (comment).
package.json
Outdated
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 think all these changes are Webpack related which we should remove
@@ -823,7 +823,7 @@ def get_desired_coupon_assignments(cls, assignment_rows): | |||
"codes listed in the Sheet. There may be an invalid coupon code in the Sheet." | |||
) | |||
product_coupon_dict = dict(product_coupon_tuples) | |||
return set((row.email, product_coupon_dict[row.code]) for row in valid_rows) # noqa: C401 | |||
return {(row.email, product_coupon_dict[row.code]) for row in valid_rows} |
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 suppose it would maintain the uniqueness of the items in this set?
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.
Yes, it will maintain the uniqueness of the items in the set. Set comprehensions, like {(row.email, product_coupon_dict[row.code]) for row in valid_rows}
, automatically ensure that the items in the set are unique, just as set() does.
For example:
In [22]: valid_rows = [
...: {"email": "[email protected]", "code": "code1"},
...: {"email": "[email protected]", "code": "code2"},
...: {"email": "[email protected]", "code": "code1"}, # Duplicate
...: ]
In [23]: product_coupon_dict = {
...: "code1": "coupon1",
...: "code2": "coupon2",
...: }
In [24]: # Using set comprehension
...: result_set_comprehension = {(row["email"], product_coupon_dict[row["code"]]) for row in valid_rows}
In [25]: result_set_comprehension
{('[email protected]', 'coupon2'), ('[email protected]', 'coupon1')}
This change was made by pyupgrade and is supported by Python’s style guidelines for clarity and performance. It also resolves the unnecessary-generator-set (C401) issue.
This holds true for similar set comprehensions you mentioned regarding uniqueness.
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.
Yes, it will maintain the uniqueness of the items in the set.
Thanks. This answers my question.
@@ -444,7 +444,7 @@ def process_row(self, row_index, row_data): | |||
row_db_record=coupon_gen_request, | |||
row_object=None, | |||
result_type=ResultType.FAILED, | |||
message="Parsing failure: {}".format(str(exc)), # noqa: UP032 | |||
message=f"Parsing failure: {exc!s}", |
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 think str would be called by default
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 think str would be called by default
Yes, in many cases, calling str()
within an f-string
is unnecessary and can be removed entirely, as the value will be converted to a string automatically. But, pyupgrade
keeps explicit type conversions like f"Parsing failure: {str(exc)}"
, which pre-commit further resolves to f"Parsing failure: {exc!s}"
for rules like RUF010.
This comment is valid for the overall comment you mentioned regarding the str.
@@ -134,7 +134,7 @@ def process_row( # noqa: C901, PLR0911 | |||
row_db_record=deferral_request, | |||
row_object=None, | |||
result_type=ResultType.FAILED, | |||
message="Parsing failure: {}".format(str(exc)), # noqa: UP032 | |||
message=f"Parsing failure: {exc!s}", |
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 similar comments about this above
I’ve left comments on specific questions and will continue to add more as needed. Some of these comments address similar requests or questions.
I’ve mentioned the review order for these PRs in the ticket here and referred in this PR description . We should first review the Webpack upgrade PR before proceeding with this PR (Python upgrade), as it depends on the Webpack upgrade and will need to be rebased afterward. I will apply a "on hold" label to this PR until the Webpack upgrade PR is reviewed and merged. |
I responded to them.
Sorry, I didn't read the additional context because I didn't feel like this might have one. Thanks for following up on the call and adding the Ideally in cases like you mentioned, we can follow the approach I'm mentioning below because that adds clarity:
|
@mudassir-hafeez It is not blocked anymore. correct? Could you rebase the PR? There are conflicts. |
f3c04e9
to
9577311
Compare
850ea97
to
f2895b6
Compare
f2895b6
to
e3dffde
Compare
Yes, it's no longer blocked. I've rebased the PR, resolved the conflicts, and tested it. It should be good to proceed now. |
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.
👍
IMPORTANT: This PR (Python upgrade) depends on the Webpack upgrade PR. Please review and merge the Webpack upgrade PR first. After it is merged, this PR will be rebased accordingly. Please follow this comment https://github.com/mitodl/hq/issues/5077#issuecomment-2276436824 to get further information.
What are the relevant tickets?
#4965
Description (What does it do?)
This PR upgrades Python to the latest supported version 3.12.4 along with some other dependencies that need to be upgraded to support it.
Screenshots (if appropriate):
How can this be tested?
Before getting started, rebuild your containers with
docker-compose build web celery
to ensure you are working with containers built with the new versions. The entire site should be smoke tested. Here is a basic list, but please add anything else as necessary:celery-1 | . courses.tasks.generate_course_certificates
celery-1 | . courses.tasks.sync_courseruns_data
celery-1 | . courses.tasks.task_sync_emeritus_course_runs
celery-1 | . courseware.tasks.change_edx_user_email_async
celery-1 | . courseware.tasks.change_edx_user_name_async
celery-1 | . courseware.tasks.create_edx_user_from_id
celery-1 | . courseware.tasks.create_user_from_id
celery-1 | . courseware.tasks.repair_faulty_courseware_users
celery-1 | . courseware.tasks.retry_failed_edx_enrollments
celery-1 | . hubspot_xpro.tasks.batch_create_hubspot_objects_chunked
celery-1 | . hubspot_xpro.tasks.batch_update_hubspot_objects_chunked
celery-1 | . hubspot_xpro.tasks.batch_upsert_associations
celery-1 | . hubspot_xpro.tasks.batch_upsert_associations_chunked
celery-1 | . hubspot_xpro.tasks.batch_upsert_hubspot_b2b_deals
celery-1 | . hubspot_xpro.tasks.batch_upsert_hubspot_b2b_deals_chunked
celery-1 | . hubspot_xpro.tasks.batch_upsert_hubspot_deals
celery-1 | . hubspot_xpro.tasks.batch_upsert_hubspot_deals_chunked
celery-1 | . hubspot_xpro.tasks.batch_upsert_hubspot_objects
celery-1 | . hubspot_xpro.tasks.sync_b2b_deal_with_hubspot
celery-1 | . hubspot_xpro.tasks.sync_contact_with_hubspot
celery-1 | . hubspot_xpro.tasks.sync_deal_with_hubspot
celery-1 | . hubspot_xpro.tasks.sync_product_with_hubspot
celery-1 | . sheets.tasks.handle_unprocessed_coupon_requests
celery-1 | . sheets.tasks.handle_unprocessed_deferral_requests
celery-1 | . sheets.tasks.handle_unprocessed_refund_requests
celery-1 | . sheets.tasks.process_coupon_assignment_sheet
celery-1 | . sheets.tasks.renew_all_file_watches
celery-1 | . sheets.tasks.renew_file_watch
celery-1 | . sheets.tasks.schedule_coupon_assignment_sheet_handling
celery-1 | . sheets.tasks.set_assignment_rows_to_enrolled
celery-1 | . sheets.tasks.update_incomplete_assignment_delivery_statuses
Additional Context