Skip to content
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

fix: move BlockKey and derived_key to avoid cyclical import #34051

Merged
merged 2 commits into from
Jan 16, 2024

Conversation

kdmccormick
Copy link
Member

@kdmccormick kdmccormick commented Jan 12, 2024

Description

Problem

After we merged this PR:

This stack trace began popping up in logs:

 Unable to load XBlock 'staffgradedxblock'
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/xblock/plugin.py", line 141, in load_classes
    yield (class_.name, cls._load_class_entry_point(class_))
  File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/xblock/plugin.py", line 70, in _load_class_entry_point
    class_ = entry_point.load()
  File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2516, in load
    return self.resolve()
  File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2522, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/staff_graded/__init__.py", line 3, in <module>
    from .staff_graded import StaffGradedXBlock
  File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/staff_graded/staff_graded.py", line 38, in <module>
    from bulk_grades.api import ScoreCSVProcessor, get_score, set_score
  File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/bulk_grades/api.py", line 18, in <module>
    from openedx.core.djangoapps.course_groups.cohorts import get_cohort
  File "/home/runner/work/edx-platform/edx-platform/openedx/core/djangoapps/course_groups/cohorts.py", line 21, in <module>
    from lms.djangoapps.courseware import courses
  File "/home/runner/work/edx-platform/edx-platform/lms/djangoapps/courseware/courses.py", line 27, in <module>
    from lms.djangoapps.course_blocks.api import get_course_blocks
ImportError: cannot import name 'get_course_blocks' from partially initialized module 'lms.djangoapps.course_blocks.api' (most likely due to a circular import) (/home/runner/work/edx-platform/edx-platform/lms/djangoapps/course_blocks/api.py)

Although the trace doesn't make it obvious, the root cause was the new imports of derived_key and BlockKey into xmodule/library_content_block.py. Those new imports come from xmodule/modulestore/store_utilities.py, which runs XBlock.load_classes() at the module level, which fails because we are still in the process of loading xmodule/library_content_block (so, a cyclical import).

Strangely, this cyclical import didn't crash the server or cause any static analysis to fail. In the interest of removing log noise and avoiding unknown buggy behavior, though, we'd like to break this import cycle.

Solution

We move both derived_key and BlockKey to xmodule/util/keys.py. We could potentially move that file to opaque-keys eventually, depending on how well we think that those concepts generalize.

Also:

  • We rename the function from derived_key to derive_key, as functions should be verbs.
  • We combine the first to parameters of derive_key (a source ContextKey and a source BlockKey) into a single parameter (a source UsageKey). In my opinion, this makes the function call easier to understand.

Supporting information

None

Testing instructions

None

Deadline

ASAP--blocks #33511

Other information

None

After we merged this PR: openedx#33920
this error began popping up in logs:

    Unable to load XBlock 'staffgradedxblock'
    ....
    ImportError: cannot import name 'get_course_blocks' from
    partially initialized module 'lms.djangoapps.course_blocks.api'
    (most likely due to a circular import) ...

The root cause was the new imports of `derived_key` and `BlockKey` into
xmodule/library_content_block.py. Those new imports come from
xmodule/modulestore/store_utilities.py, which runs
`XBlock.load_classes()` at the module level, which fails because we are
still in the process of loading xmodule/library_content_block.

As a solution, we move both `derived_key` and `BlockKey` to
xmodule/util/keys.py. We could potentially move that file to opaque-keys
eventually, depending on how well we think that those concepts generalize.

Also:

* We rename the function from derived_key to derive_key, as
  functions should be verbs.
* We combine the first to parameters of derive_key (a source ContextKey
  and a source BlockKey) into a single parameter (a source UsageKey). In
  my opinion, this makes the function call easier to understand.
@kdmccormick kdmccormick marked this pull request as ready for review January 16, 2024 14:08
UsageKeys don't have a usage_id field. This line would have crashed
if run.
Copy link
Contributor

@connorhaugh connorhaugh left a comment

Choose a reason for hiding this comment

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

I have not thoroughly tested this code with respect to v1 libs, but LGTM.

@kdmccormick kdmccormick merged commit ef0fc97 into openedx:master Jan 16, 2024
63 checks passed
@edx-pipeline-bot
Copy link
Contributor

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

@edx-pipeline-bot
Copy link
Contributor

2U Release Notice: This PR has been deployed to the edX production environment.

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

2U Release Notice: This PR has been deployed to the edX 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.

3 participants