Skip to content

feat: xblock skill verification event - #165

Merged
mariajgrimaldi merged 5 commits into
openedx:mainfrom
open-craft:navin/verification-events
Feb 17, 2023
Merged

feat: xblock skill verification event#165
mariajgrimaldi merged 5 commits into
openedx:mainfrom
open-craft:navin/verification-events

Conversation

@navinkarkera

@navinkarkera navinkarkera commented Jan 4, 2023

Copy link
Copy Markdown
Contributor

Adds data class and event to send skill verification data for an XBlock.

Updates avro serialization & de serialization just enough to support array types.

Description: The idea is that users will verify the tags/skills associated to an XBlock. We want to send this data via openedx-event signals to course-discovery and update the relevant tables.

JIRA: Private-ref: BB-6885

Dependencies: #143

Original MR: open-craft#1

Merge checklist:

  • All reviewers approved
  • CI build is green
  • Version bumped
  • Changelog record added
  • Documentation updated (not only docstrings)
  • Commits are squashed

Post merge:

  • Create a tag
  • Check new version is pushed to PyPI after tag-triggered build is
    finished.
  • Delete working branch (if not needed anymore)

Author concerns: Only support for array type is added as it is required for this event.

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Jan 4, 2023
@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @navinkarkera! Please note that it may take us up to several weeks or months to complete a review and merge your PR.

Feel free to add as much of the following information to the ticket as you can:

  • supporting documentation
  • Open edX discussion forum threads
  • timeline information ("this must be merged by XX date", and why that is)
  • partner information ("this is a course on edx.org")
  • any other information that can help Product understand the context for the PR

All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here.

Please let us know once your PR is ready for our review and all tests are green.

@mphilbrick211

Copy link
Copy Markdown

Hi @navinkarkera! Is this ready for review?

CC: @mariajgrimaldi

Comment thread openedx_events/learning/data.py Outdated
Comment thread openedx_events/event_bus/avro/tests/test_deserializer.py
@mariajgrimaldi

Copy link
Copy Markdown
Member

can we also add an instruction for testing?

@navinkarkera
navinkarkera force-pushed the navin/verification-events branch from d28c3ee to 7fe2742 Compare January 13, 2023 15:15
@navinkarkera

navinkarkera commented Jan 13, 2023

Copy link
Copy Markdown
Contributor Author

can we also add an instruction for testing?

@mariajgrimaldi Below xblock mixin/openedx-filter pipeline is making use of this signal to send user feedback about tags for the xblock. It has testing instructions included.

After completing test instructions from any one MR above, add below snippet somewhere, for example in lms/djangoapps/grades/signals/handlers.py

from openedx_events.learning.signals import XBLOCK_SKILL_VERIFIED
XBLOCK_SKILL_VERIFIED.connect(lambda **x: print(x))

Verify some tags from the UI created in the MR. It will print something like below:

edx.devstack.lms  | {'signal': <OpenEdxPublicSignal: org.openedx.content_authoring.xblock.skill.verified.v1>, 'sender': None, 'xblock_info': XBlockSkillVerificationData(usage_key='block-v1:edX+DemoX+Demo_Course+type@video+block@7503709870094870a123f697b09a692a', verified_sk
ills=[102, 103], ignored_skills=[101, 104]), 'metadata': EventsMetadata(id=UUID('f44a454c-9357-11ed-8ad8-0242ac13000a'), event_type='org.openedx.content_authoring.xblock.skill.verified.v1', minorversion=0, source='openedx/lms/web', sourcehost='lms.devstack.edx', time=dateti
me.datetime(2023, 1, 13, 15, 35, 48, 829956), sourcelib=(4, 1, 1))}

The exact section making use of this event in mixin can be found here. I am not sure how we can manually test these events independently.

@navinkarkera
navinkarkera force-pushed the navin/verification-events branch from 7fe2742 to 3392538 Compare January 13, 2023 15:25
@mphilbrick211

Copy link
Copy Markdown

Flagging this for you @mariajgrimaldi :)

@mariajgrimaldi mariajgrimaldi self-assigned this Jan 23, 2023
@mariajgrimaldi
mariajgrimaldi self-requested a review January 23, 2023 19:10
@navinkarkera
navinkarkera force-pushed the navin/verification-events branch 2 times, most recently from 99d3b41 to 38da62a Compare January 27, 2023 14:47
@navinkarkera

Copy link
Copy Markdown
Contributor Author

@mariajgrimaldi Gentle reminder, this MR is blocking openedx/taxonomy-connector#135. Kindly review.

@mariajgrimaldi

Copy link
Copy Markdown
Member

@navinkarkera: thanks for the patience! I'll be reviewing this on Monday.

@mariajgrimaldi mariajgrimaldi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I appreciate your patience! 🥇 This looks good I just left a few comments, mainly regarding the avro changes. I'll be waiting for your comments.

return deserializer(data)
elif data_type in PYTHON_TYPE_TO_AVRO_MAPPING:
return data
elif PYTHON_TYPE_TO_AVRO_MAPPING.get(data_type_origin) == "array":

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why don't you try 🤔:

Suggested change
elif PYTHON_TYPE_TO_AVRO_MAPPING.get(data_type_origin) == "array":
elif data_type_origin in PYTHON_TYPE_TO_AVRO_MAPPING.get(data_type_origin):

Or this type checking is just for lists? Is there a reason that dicts shouldn't be checked?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@mariajgrimaldi I have only implemented support for list/array as dicts might require more change.

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.

Alternatively, can we just do if data_type_origin == list? It seems odd to work backwards from the map.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rgraber Makes sense.
Just in case we want to support other array like python types like set, the current condition would not require any change.

I can still change it to data_type_origin == list if you think my statement does not make sense.

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 still think we should go with == list for clarity

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rgraber Done.

Comment on lines +214 to +221
with self.assertRaises(TypeError):
deserializer.from_dict(initial_dict)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why should this fail?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Handling nested lists (with annotation) support again introduces complexity and I did not implement it as it is not required as of now.

If we remove inner list type annotation, i.e. change the type to List[list] it works because the schema is becomes: {'name': 'list_input', 'type': {'type': 'array', 'items': 'array'}}

    def test_deserialization_of_nested_list_works(self):
        SIGNAL = create_simple_signal({"list_input": List[list]})
        initial_dict = {"list_input": [[1, 3], [4, 5]]}
        deserializer = AvroSignalDeserializer(SIGNAL)
        data = deserializer.from_dict(initial_dict)
        self.assertEqual(data, initial_dict)

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.

Do we want List[list] to work? Doesn't that open us up to issues with something like [[Object, 'a'], [1, "bananas"]]?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rgraber Good point! I have updated it to allow only simple types like int, str, bool etc.

Comment thread openedx_events/event_bus/avro/schema.py Outdated
Comment thread openedx_events/event_bus/avro/serializer.py
@mariajgrimaldi

Copy link
Copy Markdown
Member

Don't forget to rebase with the main branch!

@navinkarkera
navinkarkera force-pushed the navin/verification-events branch from 38da62a to dcda85d Compare January 31, 2023 11:28

@navinkarkera navinkarkera left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@mariajgrimaldi Replied to your queries inline and rebased with main.

return deserializer(data)
elif data_type in PYTHON_TYPE_TO_AVRO_MAPPING:
return data
elif PYTHON_TYPE_TO_AVRO_MAPPING.get(data_type_origin) == "array":

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@mariajgrimaldi I have only implemented support for list/array as dicts might require more change.

Comment thread openedx_events/event_bus/avro/schema.py Outdated
Comment thread openedx_events/event_bus/avro/serializer.py
Comment on lines +214 to +221
with self.assertRaises(TypeError):
deserializer.from_dict(initial_dict)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Handling nested lists (with annotation) support again introduces complexity and I did not implement it as it is not required as of now.

If we remove inner list type annotation, i.e. change the type to List[list] it works because the schema is becomes: {'name': 'list_input', 'type': {'type': 'array', 'items': 'array'}}

    def test_deserialization_of_nested_list_works(self):
        SIGNAL = create_simple_signal({"list_input": List[list]})
        initial_dict = {"list_input": [[1, 3], [4, 5]]}
        deserializer = AvroSignalDeserializer(SIGNAL)
        data = deserializer.from_dict(initial_dict)
        self.assertEqual(data, initial_dict)

@mariajgrimaldi

Copy link
Copy Markdown
Member

Hello there folks! @robrap @rgraber @timmc-edx. We're introducing these changes to the library, and I wanted to ensure you're OK with them. Please let us know! 😋

@rgraber rgraber left a comment

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.

Couple questions. In general, I think more comments about what get_args and get_origin are expected to return would make it easier to follow.

Comment thread openedx_events/event_bus/avro/deserializer.py
return deserializer(data)
elif data_type in PYTHON_TYPE_TO_AVRO_MAPPING:
return data
elif PYTHON_TYPE_TO_AVRO_MAPPING.get(data_type_origin) == "array":

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.

Alternatively, can we just do if data_type_origin == list? It seems odd to work backwards from the map.

raise TypeError(
"List without annotation type is not supported. The argument should be a type, for eg., List[int]"
)
if arg_data_type[0] in PYTHON_TYPE_TO_AVRO_MAPPING:

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 this will break on List[CourseKey] (or other custom-serialized class). That's ok but we should be very clear in exactly how much support we have for array types.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As I mentioned in one of replies above, I have updated the code to only support basic types inside lists and it will raise meaningful error if unsupported type is passed.

Comment on lines +214 to +221
with self.assertRaises(TypeError):
deserializer.from_dict(initial_dict)

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.

Do we want List[list] to work? Doesn't that open us up to issues with something like [[Object, 'a'], [1, "bananas"]]?

@robrap robrap added the event-bus Work related to the Event Bus. label Feb 6, 2023
@navinkarkera
navinkarkera force-pushed the navin/verification-events branch 2 times, most recently from 8a33abb to 0009eda Compare February 14, 2023 06:44
@navinkarkera

Copy link
Copy Markdown
Contributor Author

@mariajgrimaldi @rgraber Gentle reminder. Let me know if changes are required, else we should be good to merge.

@mariajgrimaldi

Copy link
Copy Markdown
Member

we would like your approval here @rgraber :) thanks!

@navinkarkera
navinkarkera force-pushed the navin/verification-events branch from 0009eda to b9c11a2 Compare February 16, 2023 08:04

@rgraber rgraber left a comment

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.

Couple more things, but overall looks great!

return deserializer(data)
elif data_type in PYTHON_TYPE_TO_AVRO_MAPPING:
return data
elif PYTHON_TYPE_TO_AVRO_MAPPING.get(data_type_origin) == "array":

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 still think we should go with == list for clarity

Comment thread openedx_events/event_bus/avro/tests/test_deserializer.py
with self.assertRaises(Exception):
schema_from_signal(DICT_SIGNAL)

def test_throw_exception_to_list_or_dict_types_without_annotation(self):

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.

Isn't this just a duplicate of the above test? Did you mean to rename?

@navinkarkera navinkarkera Feb 17, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rgraber Thanks for catching it, I indeed meant to rename the function.

Update: Actually it was helping in code coverage, so I have updated the test to include a signal with List type.

Adds data class and event to send skill verification data for an XBlock.

feat: add support for array avro types

chore: add changelog

docs: update signals docs to be more generic

test: fix code coverage

refactor: add docstrings
@navinkarkera
navinkarkera force-pushed the navin/verification-events branch from 5f62d9f to 6b6b646 Compare February 17, 2023 07:03

@rgraber rgraber left a comment

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.

Looks good, thanks!

@mariajgrimaldi mariajgrimaldi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

great job! thank you

@mariajgrimaldi
mariajgrimaldi merged commit 26a8dd5 into openedx:main Feb 17, 2023
@openedx-webhooks

Copy link
Copy Markdown

@navinkarkera 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future.

@mariajgrimaldi

Copy link
Copy Markdown
Member

@navinkarkera: the new release is out!

@navinkarkera

Copy link
Copy Markdown
Contributor Author

@mariajgrimaldi @rgraber Thank you!

navinkarkera added a commit to open-craft/openedx-events that referenced this pull request Feb 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

event-bus Work related to the Event Bus. open-source-contribution PR author is not from Axim or 2U

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants