Skip to content

BOM-2245 : Unpin python-dateutil#30255

Merged
mumarkhan999 merged 1 commit intomasterfrom
bom-2245-attempt-3
May 31, 2022
Merged

BOM-2245 : Unpin python-dateutil#30255
mumarkhan999 merged 1 commit intomasterfrom
bom-2245-attempt-3

Conversation

@mumarkhan999
Copy link
Contributor

@mumarkhan999 mumarkhan999 commented Apr 15, 2022

Last time we tried to bump the version of python-dateutil (PR#27196) we got this error
image

Line 585 in method get_course_assignments was causing the error at that time

https://github.com/openedx/edx-platform/blob/072b6b8875e2a6323b6666998a3bf5c5e6444039/lms/djangoapps/courseware/courses.py#L585

The reason of the error was that start datetime object which we were getting from BlockStructureBlockData wasn't updated as per the latest version of python-dateutil
https://github.com/openedx/edx-platform/blob/072b6b8875e2a6323b6666998a3bf5c5e6444039/lms/djangoapps/courseware/courses.py#L584

https://github.com/openedx/edx-platform/blob/072b6b8875e2a6323b6666998a3bf5c5e6444039/openedx/core/djangoapps/content/block_structure/block_structure.py#L396

The tzlocal object assigned to tzinfo variable of start date was like this
image
But according to the latest version of python-dateutil it should have been like this
image

So now as we know that the problem is with the outdated datetime objects. We should update them and this is what we are doing in this PR. We have added a patch where we are creating updated datetime objects using the outdated ones and using them for calculations and comparisons.

How did I test?

I used follwoing 3 branches to test this solution.

  1. bom-2245-attempt-3 (current branch)
    • Has updated version of python-dateutil
    • Has patch where we are creating updated datetime objects from the outdated ones
  2. test-bom-2245-attempt-3
    • Has updated version of python-dateutil
    • Has no patch, we're using outdated datetime objects
  3. master
    • Has outdated version of python-dateutil
    • Has no patch

I also created a code snippet to replicate the behavior of get_course_assingments method, so that I can trigger that behavior from lms-shell

from xmodule.modulestore.django import modulestore
from opaque_keys.edx.keys import CourseKey
from lms.djangoapps.course_blocks.api import get_course_blocks
from django.contrib.auth.models import User
from datetime import datetime
import pytz


course_key_string = 'course-v1:edX+DemoX+Demo_Course'
course_key = CourseKey.from_string(course_key_string)  
store = modulestore()
course_usage_key = store.make_course_usage_key(course_key)

user = User.objects.get(username='admin')
block_data = get_course_blocks(user, course_usage_key, allow_start_dates_in_future=True, include_completion=True)

dates = []

for section_key in block_data.get_children(course_usage_key):
    for subsection_key in block_data.get_children(section_key):
        due = block_data.get_xblock_field(subsection_key, 'due')
        graded = block_data.get_xblock_field(subsection_key, 'graded', False)
        if due and graded:
            start = block_data.get_xblock_field(subsection_key, 'start')
            dates.append(start)



print(dates)
vars(dates[0].tzinfo)

now = datetime.now(pytz.UTC)
print(now)
print(now < dates[0])

So I executed the above code snippet on the mentioned branches and I got the following outputs:

For master
  • The datetime objects are outdated
  • The date comparisons are working fine with the outdated version of python-dateutil

image

When I switched from master to bom-2245-attempt-3 (current branch)
  • The datetime objects are updated due to the patch we have applied
  • The date comparsons are working fine with the updated version of python-dateutil

image

When I switched from bom-2245-attempt-3 to test-bom-2245-attempt-3
  • The datetime objects are not updated due to the absense of patch
  • The date comparisons are not working as datetime objects are outdated

image

@mumarkhan999 mumarkhan999 force-pushed the bom-2245-attempt-3 branch 5 times, most recently from f792247 to 2b961fb Compare April 15, 2022 19:43
@mumarkhan999 mumarkhan999 self-assigned this Apr 15, 2022
@mumarkhan999 mumarkhan999 force-pushed the bom-2245-attempt-3 branch 7 times, most recently from 7c95ff6 to 23db538 Compare April 18, 2022 10:50
@awais786 awais786 requested a review from jmbowman May 6, 2022 15:03
@mumarkhan999
Copy link
Contributor Author

Hi @regisb , can you please have a look at this PR. It's related to python-dateutil version update.
You have worked on python-dateutil related issues so If you can review this one as well it would be great.

@mumarkhan999 mumarkhan999 requested a review from regisb May 11, 2022 12:43
Copy link
Contributor

@regisb regisb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for resuming work on this issue. The fix matches my analysis from here and it looks good to me!

@mumarkhan999 mumarkhan999 requested a review from ormsbee May 12, 2022 07:27
return datetime(
year=xblock_field.year, month=xblock_field.month, day=xblock_field.day,
hour=xblock_field.hour, minute=xblock_field.minute, second=xblock_field.second,
tzinfo=tzlocal()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see anywhere else we use tzlocal in edx-platform, and the Django docs indicate that UTC is generally used to store in MySQL when USE_TZ = True.

Copy link
Contributor Author

@mumarkhan999 mumarkhan999 May 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we check the course_outline on sandbox where USE_TZ = True, we will find that tzlocal is being used multiple times

Code snippet to check the course outline:

from django.contrib.auth.models import User
from django.test import RequestFactory
from openedx.features.course_experience.utils import get_course_outline_block_tree

user = User.objects.get(username='admin')
request = RequestFactory().get(u'/')
request.user = user
course_key_string = 'course-v1:edX+DemoX+Demo_Course'


course_outline = get_course_outline_block_tree(request, course_key_string, request.user)
print(course_outline)

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I forgot that this is coming from a cache instead of the database. Yes, in that sense it makes sense to just replicate the time zone they had before being cached.

import pytest
import pytz
from boto.exception import BotoServerError
from dateutil.zoneinfo import gettz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not the original dateutil.tz? According to the python-dateutil docs, the method you have here is deprecated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.
Two tests were failing when I first created this PR that's why I tried to use this method.
But now tests are passing even after removing this method. So now using the original dateutil.tz
as you suggested.

import dateutil
import pytz
import edx_api_doc_tools as apidocs
from dateutil.zoneinfo import gettz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

networkx<2.6
# numpy>=1.17 is required for matplotlib>=3.5.1
# and numpy>=1.17.0 caused failures in importing numpy in code-jail environment.
matplotlib==3.4.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it would upgrade matplotlib from 3.3.4 to 3.4.0, but I don't see a corresponding change in py38.txt. And I'd rather not risk upgrading that in codejail at the same time as we attempt the python-dateutil upgrade, so can we shift this back to matplotlib<3.4.0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Will be upgraded in separate PR if required.

@mumarkhan999 mumarkhan999 force-pushed the bom-2245-attempt-3 branch 2 times, most recently from a5ef5b3 to f302d2a Compare May 18, 2022 08:34
Copy link
Contributor

@jmbowman jmbowman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for helping unravel this! I still think we'll want to stop using pickle on datetimes altogether in the future to avoid further upgrade hassles, but hopefully this will get us through this upgrade at least.

Are there still any cache purges that we'll need to coordinate with SRE during deployment, or do you think this should cover it?

return datetime(
year=xblock_field.year, month=xblock_field.month, day=xblock_field.day,
hour=xblock_field.hour, minute=xblock_field.minute, second=xblock_field.second,
tzinfo=tzlocal()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I forgot that this is coming from a cache instead of the database. Yes, in that sense it makes sense to just replicate the time zone they had before being cached.

@mumarkhan999
Copy link
Contributor Author

Thanks for helping unravel this! I still think we'll want to stop using pickle on datetimes altogether in the future to avoid further upgrade hassles, but hopefully this will get us through this upgrade at least.

Are there still any cache purges that we'll need to coordinate with SRE during deployment, or do you think this should cover it?

I think that we will not need any cache purges. But if somethings goes wrong, we can rely on that as a backup plan.

@mumarkhan999 mumarkhan999 merged commit a631324 into master May 31, 2022
@mumarkhan999 mumarkhan999 deleted the bom-2245-attempt-3 branch May 31, 2022 13:14
@edx-pipeline-bot
Copy link
Contributor

EdX Release Notice: This PR has been deployed to the staging environment in preparation for a release to production.

@edx-pipeline-bot
Copy link
Contributor

EdX Release Notice: This PR has been deployed to the production environment.

@edx-pipeline-bot
Copy link
Contributor

EdX Release Notice: This PR has been rolled back from the production environment.

@edx-pipeline-bot
Copy link
Contributor

EdX Release Notice: This PR has been deployed to the production environment.

1 similar comment
@edx-pipeline-bot
Copy link
Contributor

EdX Release Notice: This PR has been deployed to the production environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants