Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions cms/djangoapps/contentstore/views/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,11 @@ def _prepare_runtime_for_preview(request, block, field_data):
# stick the license wrapper in front
wrappers.insert(0, partial(wrap_with_license, mako_service=mako_service))

preview_anonymous_user_id = 'student'
anonymous_user_id = deprecated_anonymous_user_id = 'student'
if individualize_anonymous_user_id(course_id):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Am I right in thinking that individualize_anonymous_user_id() is leftover rollout code and that just makes preview behavior incorrect now and doesn't need to be here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I guess dealing with that is not worth adding to this PR in terms of risk either way.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It seems to have been added on purpose: #30248.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, okay, good to not touch... 😛

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Misc. note, but now I think I better understand why the anonymous ID parsing in capa content that I've seen has something like this:

import random
try:
	randomseed = int(anonymous_student_id, 16)
except:
	randomseed = 1
random.seed(randomseed)

... so it doesn't blow up the problem in preview where it can't parse because the strings are not hex strings. There's no need to change this behavior–I just put this note here because it was something that was puzzling me.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, the motivation for that is that they want to have a handful of random variables that are generated the same way for a given student across multiple problems so that they can tie them together. Like if problem 1 asks you to calculate your monthly mortgage payments based on some variables, and then problem 2 asks you what those payments would be if you paid made a $100K payment after the first year, etc.

@Agrendalath Agrendalath May 2, 2023

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Unless I'm missing something, the hash function works the same way as int(hex_string, 16) for hex values. It works for non-hex strings, too (without raising an exception).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would actually be a very useful feature if we could assign variables to some namespace that lives across problems and let XBlocks access that–people have basically hacked that together in a few different ways over the years. Maybe as an XBlock service some day, though we'd have to think through the implications pretty critically.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unless I'm missing something, the hash function works the same way as int(hex_string, 16) for hex values. It works for non-hex strings, too.

Python's builtin hash function is only guaranteed to return consistently within a given run of a Python process, so it would be a bad fit for deriving anything stable.

edx-platform on  ormsbee-anonymous-id-xb-service via 🐍 v3.8.12 (tutor_nightly) is 📦 v0.1.0 took 12s
❯ python
Python 3.8.12 (default, Dec 10 2021, 16:41:45)
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("Hello World!")
6517261053207716808
>>> hash("Hello World!")
6517261053207716808
>>>

edx-platform on  ormsbee-anonymous-id-xb-service via 🐍 v3.8.12 (tutor_nightly) is 📦 v0.1.0 took 2m18s
❯ python
Python 3.8.12 (default, Dec 10 2021, 16:41:45)
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("Hello World!")
740855705488943589
>>> hash("Hello World!")
740855705488943589
>>>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah, good point. I forgot it's consistent only for numeric types.

# There are blocks (capa, html, and video) where we do not want to scope
# the anonymous_user_id to specific courses. These are captured in the
# block attribute 'requires_per_student_anonymous_id'. Please note,
# the course_id field in AnynomousUserID model is blank if value is None.
if getattr(block, 'requires_per_student_anonymous_id', False):
preview_anonymous_user_id = anonymous_id_for_user(request.user, None)
else:
preview_anonymous_user_id = anonymous_id_for_user(request.user, course_id)
anonymous_user_id = anonymous_id_for_user(request.user, course_id)
# See the docstring of `DjangoXBlockUserService`.
deprecated_anonymous_user_id = anonymous_id_for_user(request.user, None)

services = {
"field-data": field_data,
Expand All @@ -213,7 +208,8 @@ def _prepare_runtime_for_preview(request, block, field_data):
"user": DjangoXBlockUserService(
request.user,
user_role=get_user_role(request.user, course_id),
anonymous_user_id=preview_anonymous_user_id,
anonymous_user_id=anonymous_user_id,
deprecated_anonymous_user_id=deprecated_anonymous_user_id,
),
"partitions": StudioPartitionService(course_id=course_id),
"teams_configuration": TeamsConfigurationService(),
Expand Down
14 changes: 10 additions & 4 deletions cms/djangoapps/contentstore/views/tests/test_preview.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"""
Tests for contentstore.views.preview.py
"""


import re
from unittest import mock

import ddt
from common.djangoapps.xblock_django.constants import ATTR_KEY_ANONYMOUS_USER_ID, ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID
from django.test.client import Client, RequestFactory
from django.test.utils import override_settings
from edx_toggles.toggles.testutils import override_waffle_flag
Expand Down Expand Up @@ -309,7 +308,10 @@ def test_anonymous_user_id_individual_per_student(self):
block=block,
field_data=mock.Mock(),
)
assert block.runtime.anonymous_student_id == '26262401c528d7c4a6bbeabe0455ec46'
deprecated_anonymous_user_id = (
block.runtime.service(block, 'user').get_current_user().opt_attrs.get(ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID)
)
assert deprecated_anonymous_user_id == '26262401c528d7c4a6bbeabe0455ec46'

@override_waffle_flag(INDIVIDUALIZE_ANONYMOUS_USER_ID, active=True)
def test_anonymous_user_id_individual_per_course(self):
Expand All @@ -321,4 +323,8 @@ def test_anonymous_user_id_individual_per_course(self):
block=block,
field_data=mock.Mock(),
)
assert block.runtime.anonymous_student_id == 'ad503f629b55c531fed2e45aa17a3368'

anonymous_user_id = (
block.runtime.service(block, 'user').get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
)
assert anonymous_user_id == 'ad503f629b55c531fed2e45aa17a3368'
1 change: 1 addition & 0 deletions common/djangoapps/xblock_django/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

# Optional attributes stored on the XBlockUser
ATTR_KEY_ANONYMOUS_USER_ID = 'edx-platform.anonymous_user_id'
ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID = 'edx-platform.deprecated_anonymous_user_id'
ATTR_KEY_REQUEST_COUNTRY_CODE = 'edx-platform.request_country_code'
ATTR_KEY_IS_AUTHENTICATED = 'edx-platform.is_authenticated'
ATTR_KEY_USER_ID = 'edx-platform.user_id'
Expand Down
6 changes: 6 additions & 0 deletions common/djangoapps/xblock_django/user_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from .constants import (
ATTR_KEY_ANONYMOUS_USER_ID,
ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID,
ATTR_KEY_IS_AUTHENTICATED,
ATTR_KEY_REQUEST_COUNTRY_CODE,
ATTR_KEY_USER_ID,
Expand All @@ -38,13 +39,17 @@ def __init__(self, django_user, **kwargs):
user_is_staff(bool): optional - whether the user is staff in the course
user_role(str): optional -- user's role in the course ('staff', 'instructor', or 'student')
anonymous_user_id(str): optional - anonymous_user_id for the user in the course
deprecated_anonymous_user_id(str): optional - There are XBlocks (CAPA and HTML) that use the per-student
(course-agnostic) anonymized ID. To preserve backward compatibility, we will continue to provide it.
Using course-specific anonymous user ID (`anonymous_user_id`) is a preferred approach.
request_country_code(str): optional -- country code determined from the user's request IP address.
"""
super().__init__(**kwargs)
self._django_user = django_user
self._user_is_staff = kwargs.get('user_is_staff', False)
self._user_role = kwargs.get('user_role', 'student')
self._anonymous_user_id = kwargs.get('anonymous_user_id', None)
self._deprecated_anonymous_user_id = kwargs.get('deprecated_anonymous_user_id', None)
self._request_country_code = kwargs.get('request_country_code', None)

def get_current_user(self):
Expand Down Expand Up @@ -111,6 +116,7 @@ def _convert_django_user_to_xblock_user(self, django_user):
xblock_user.full_name = full_name
xblock_user.emails = [django_user.email]
xblock_user.opt_attrs[ATTR_KEY_ANONYMOUS_USER_ID] = self._anonymous_user_id
xblock_user.opt_attrs[ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID] = self._deprecated_anonymous_user_id
xblock_user.opt_attrs[ATTR_KEY_IS_AUTHENTICATED] = True
xblock_user.opt_attrs[ATTR_KEY_REQUEST_COUNTRY_CODE] = self._request_country_code
xblock_user.opt_attrs[ATTR_KEY_USER_ID] = django_user.id
Expand Down
15 changes: 3 additions & 12 deletions lms/djangoapps/courseware/block_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,23 +493,14 @@ def inner_get_block(block):
will_recheck_access=will_recheck_access,
)

# These modules store data using the anonymous_student_id as a key.
# To prevent loss of data, we will continue to provide old modules with
# the per-student anonymized id (as we have in the past),
# while giving selected modules a per-course anonymized id.
# As we have the time to manually test more modules, we can add to the list
# of modules that get the per-course anonymized id.
if getattr(block, 'requires_per_student_anonymous_id', False):
anonymous_student_id = anonymous_id_for_user(user, None)
else:
anonymous_student_id = anonymous_id_for_user(user, course_id)

user_is_staff = bool(has_access(user, 'staff', block.location, course_id))
user_service = DjangoXBlockUserService(
user,
user_is_staff=user_is_staff,
user_role=get_user_role(user, course_id),
anonymous_user_id=anonymous_student_id,
anonymous_user_id=anonymous_id_for_user(user, course_id),
# See the docstring of `DjangoXBlockUserService`.
deprecated_anonymous_user_id=anonymous_id_for_user(user, None),
request_country_code=user_location,
)

Expand Down
27 changes: 18 additions & 9 deletions lms/djangoapps/courseware/tests/test_block_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
from common.djangoapps.student.tests.factories import GlobalStaffFactory
from common.djangoapps.student.tests.factories import RequestFactoryNoCsrf
from common.djangoapps.student.tests.factories import UserFactory
from common.djangoapps.xblock_django.constants import ATTR_KEY_ANONYMOUS_USER_ID
from common.djangoapps.xblock_django.constants import ATTR_KEY_ANONYMOUS_USER_ID, ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID
from lms.djangoapps.badges.tests.factories import BadgeClassFactory
from lms.djangoapps.badges.tests.test_models import get_image
from lms.djangoapps.courseware import block_render as render
Expand Down Expand Up @@ -1858,14 +1858,14 @@ def test_histogram_enabled_for_scored_xblocks(self):

PER_COURSE_ANONYMIZED_XBLOCKS = (
LTIBlock,
VideoBlock,
)
PER_STUDENT_ANONYMIZED_XBLOCKS = [
AboutBlock,
CourseInfoBlock,
HtmlBlock,
ProblemBlock,
StaticTabBlock,
VideoBlock,
]


Expand All @@ -1886,7 +1886,7 @@ def setUp(self):
self.user = UserFactory()

@patch('lms.djangoapps.courseware.block_render.has_access', Mock(return_value=True, autospec=True))
def _get_anonymous_id(self, course_id, xblock_class): # lint-amnesty, pylint: disable=missing-function-docstring
def _get_anonymous_id(self, course_id, xblock_class, should_get_deprecated_id: bool): # lint-amnesty, pylint: disable=missing-function-docstring
location = course_id.make_usage_key('dummy_category', 'dummy_name')
block = Mock(
spec=xblock_class,
Expand Down Expand Up @@ -1924,21 +1924,24 @@ def _get_anonymous_id(self, course_id, xblock_class): # lint-amnesty, pylint: d
course=self.course,
)
current_user = rendered_block.runtime.service(rendered_block, 'user').get_current_user()

if should_get_deprecated_id:
return current_user.opt_attrs.get(ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID)
return current_user.opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)

@ddt.data(*PER_STUDENT_ANONYMIZED_XBLOCKS)
def test_per_student_anonymized_id(self, block_class):
for course_id in ('MITx/6.00x/2012_Fall', 'MITx/6.00x/2013_Spring'):
assert 'de619ab51c7f4e9c7216b4644c24f3b5' == \
self._get_anonymous_id(CourseKey.from_string(course_id), block_class)
self._get_anonymous_id(CourseKey.from_string(course_id), block_class, True)

@ddt.data(*PER_COURSE_ANONYMIZED_XBLOCKS)
def test_per_course_anonymized_id(self, xblock_class):
assert '0c706d119cad686d28067412b9178454' == \
self._get_anonymous_id(CourseKey.from_string('MITx/6.00x/2012_Fall'), xblock_class)
self._get_anonymous_id(CourseKey.from_string('MITx/6.00x/2012_Fall'), xblock_class, False)

assert 'e9969c28c12c8efa6e987d6dbeedeb0b' == \
self._get_anonymous_id(CourseKey.from_string('MITx/6.00x/2013_Spring'), xblock_class)
self._get_anonymous_id(CourseKey.from_string('MITx/6.00x/2013_Spring'), xblock_class, False)


@patch('common.djangoapps.track.views.eventtracker', autospec=True)
Expand Down Expand Up @@ -2720,7 +2723,9 @@ def test_anonymous_student_id_bug(self):
course=self.course,
)
# Ensure the problem block returns a per-user anonymous id
assert self.problem_block.runtime.anonymous_student_id == anonymous_id_for_user(self.user, None)
assert self.problem_block.runtime.service(self.problem_block, 'user').get_current_user().opt_attrs.get(
ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID
) == anonymous_id_for_user(self.user, None)

_ = render.prepare_runtime_for_user(
self.user,
Expand All @@ -2732,10 +2737,14 @@ def test_anonymous_student_id_bug(self):
course=self.course,
)
# Ensure the vertical block returns a per-course+user anonymous id
assert self.block.runtime.anonymous_student_id == anonymous_id_for_user(self.user, self.course.id)
assert self.block.runtime.service(self.block, 'user').get_current_user().opt_attrs.get(
ATTR_KEY_ANONYMOUS_USER_ID
) == anonymous_id_for_user(self.user, self.course.id)

# Ensure the problem runtime's anonymous student ID is unchanged after the above call.
assert self.problem_block.runtime.anonymous_student_id == anonymous_id_for_user(self.user, None)
assert self.problem_block.runtime.service(self.problem_block, 'user').get_current_user().opt_attrs.get(
ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID
) == anonymous_id_for_user(self.user, None)

def test_user_service_with_anonymous_user(self):
_ = render.prepare_runtime_for_user(
Expand Down
2 changes: 1 addition & 1 deletion openedx/core/djangoapps/schedules/tests/test_resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def create_resolver(self, user_start_date_offset=8):
def test_schedule_context(self):
resolver = self.create_resolver()
# using this to make sure the select_related stays intact
with self.assertNumQueries(38):
with self.assertNumQueries(40):
sc = resolver.get_schedules()
schedules = list(sc)
apple_logo_url = 'http://email-media.s3.amazonaws.com/edX/2021/store_apple_229x78.jpg'
Expand Down
8 changes: 8 additions & 0 deletions openedx/core/djangoapps/xblock/runtime/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from urllib.parse import urljoin # pylint: disable=import-error

import crum
from common.djangoapps.student.models import anonymous_id_for_user
from completion.waffle import ENABLE_COMPLETION_TRACKING_SWITCH
from completion.models import BlockCompletion
from completion.services import CompletionService
Expand Down Expand Up @@ -235,12 +236,19 @@ def service(self, block, service_name):
elif service_name == "completion":
return CompletionService(user=self.user, context_key=context_key)
elif service_name == "user":
if self.user.is_anonymous:
deprecated_anonymous_student_id = self.user_id
else:
deprecated_anonymous_student_id = anonymous_id_for_user(self.user, course_id=None)

return DjangoXBlockUserService(
self.user,
# The value should be updated to whether the user is staff in the context when Blockstore runtime adds
# support for courses.
user_is_staff=self.user.is_staff,
anonymous_user_id=self.anonymous_student_id,
# See the docstring of `DjangoXBlockUserService`.
deprecated_anonymous_user_id=deprecated_anonymous_student_id
)
elif service_name == "mako":
if self.system.student_data_mode == XBlockRuntimeSystem.STUDENT_DATA_EPHEMERAL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test_queries(self):

# Fetch the view and verify that the query counts haven't changed
# TODO: decrease query count as part of REVO-28
with self.assertNumQueries(51, table_ignorelist=QUERY_COUNT_TABLE_IGNORELIST):
with self.assertNumQueries(53, table_ignorelist=QUERY_COUNT_TABLE_IGNORELIST):
with check_mongo_calls(3):
url = course_updates_url(self.course)
self.client.get(url)
5 changes: 2 additions & 3 deletions xmodule/capa_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
)
from xmodule.xml_block import XmlMixin
from common.djangoapps.xblock_django.constants import (
ATTR_KEY_ANONYMOUS_USER_ID,
ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID,
ATTR_KEY_USER_IS_STAFF,
ATTR_KEY_USER_ID,
)
Expand Down Expand Up @@ -165,7 +165,6 @@ class ProblemBlock(
icon_class = 'problem'

uses_xmodule_styles_setup = True
requires_per_student_anonymous_id = True

preview_view_js = {
'js': [
Expand Down Expand Up @@ -822,7 +821,7 @@ def new_lcp(self, state, text=None):
text = self.data

user_service = self.runtime.service(self, 'user')
anonymous_student_id = user_service.get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
anonymous_student_id = user_service.get_current_user().opt_attrs.get(ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID)
seed = user_service.get_current_user().opt_attrs.get(ATTR_KEY_USER_ID) or 0

sandbox_service = self.runtime.service(self, 'sandbox')
Expand Down
10 changes: 7 additions & 3 deletions xmodule/html_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Boolean, List, Scope, String
from common.djangoapps.xblock_django.constants import ATTR_KEY_ANONYMOUS_USER_ID

from common.djangoapps.xblock_django.constants import ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID
from xmodule.contentstore.content import StaticContent
from xmodule.editing_block import EditingMixin
from xmodule.edxnotes_utils import edxnotes
Expand Down Expand Up @@ -119,7 +120,11 @@ def get_html(self):
""" Returns html required for rendering the block. """
if self.data:
data = self.data
user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
user_id = (
self.runtime.service(self, 'user')
.get_current_user()
.opt_attrs.get(ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID)
)
if user_id:
data = data.replace("%%USER_ID%%", user_id)
data = data.replace("%%COURSE_ID%%", str(self.scope_ids.usage_id.context_key))
Expand Down Expand Up @@ -150,7 +155,6 @@ def studio_view(self, _context):
preview_view_css = {'scss': [resource_string(__name__, 'css/html/display.scss')]}

uses_xmodule_styles_setup = True
requires_per_student_anonymous_id = True

mako_template = "widgets/html-edit.html"
resources_dir = None
Expand Down
2 changes: 2 additions & 0 deletions xmodule/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def get_test_system(
user_service = StubUserService(
user=user,
anonymous_user_id='student',
deprecated_anonymous_user_id='student',
user_is_staff=user_is_staff,
user_role='student',
request_country_code=user_location,
Expand Down Expand Up @@ -202,6 +203,7 @@ def prepare_block_runtime(
user_service = StubUserService(
user=user,
anonymous_user_id='student',
deprecated_anonymous_user_id='student',
user_is_staff=user_is_staff,
user_role='student',
request_country_code=user_location,
Expand Down
3 changes: 3 additions & 0 deletions xmodule/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ def __init__(self,
user_is_staff=False,
user_role=None,
anonymous_user_id=None,
deprecated_anonymous_user_id=None,
request_country_code=None,
**kwargs):
self.user = user
self.user_is_staff = user_is_staff
self.user_role = user_role
self.anonymous_user_id = anonymous_user_id
self.deprecated_anonymous_user_id = deprecated_anonymous_user_id
self.request_country_code = request_country_code
self._django_user = user
super().__init__(**kwargs)
Expand All @@ -84,6 +86,7 @@ def get_current_user(self):
user = XBlockUser()
if self.user and self.user.is_authenticated:
user.opt_attrs['edx-platform.anonymous_user_id'] = self.anonymous_user_id
user.opt_attrs['edx-platform.deprecated_anonymous_user_id'] = self.deprecated_anonymous_user_id
user.opt_attrs['edx-platform.request_country_code'] = self.request_country_code
user.opt_attrs['edx-platform.user_is_staff'] = self.user_is_staff
user.opt_attrs['edx-platform.user_id'] = self.user.id
Expand Down
1 change: 1 addition & 0 deletions xmodule/tests/test_html_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def test_substitution_without_anonymous_student_id(self):
field_data = DictFieldData({'data': sample_xml})
module_system = get_test_system(user=AnonymousUser())
block = HtmlBlock(module_system, field_data, Mock())
block.runtime.service(block, 'user')._deprecated_anonymous_user_id = '' # pylint: disable=protected-access
assert block.get_html() == sample_xml


Expand Down
1 change: 0 additions & 1 deletion xmodule/video_block/video_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ class VideoBlock(
js_module_name = "TabsEditingDescriptor"

uses_xmodule_styles_setup = True
requires_per_student_anonymous_id = True

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The VideoBlock does not use the anonymous student ID anywhere. The only usage of the user service is for requesting the ATTR_KEY_REQUEST_COUNTRY_CODE.


def get_transcripts_for_student(self, transcripts):
"""Return transcript information necessary for rendering the XModule student view.
Expand Down
3 changes: 3 additions & 0 deletions xmodule/x_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,9 @@ def anonymous_student_id(self):
Returns the anonymous user ID for the current user and course.

Deprecated in favor of the user service.

NOTE: This method returns a course-specific anonymous user ID. If you are looking for the student-specific one,
use `ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID` from the user service.
"""
warnings.warn(
'runtime.anonymous_student_id is deprecated. Please use the user service instead.',
Expand Down