Skip to content

Commit

Permalink
WIP better separation of mixin vs pure v2
Browse files Browse the repository at this point in the history
  • Loading branch information
bradenmacdonald committed Jun 1, 2024
1 parent aa1cd10 commit a56d8db
Showing 1 changed file with 40 additions and 36 deletions.
76 changes: 40 additions & 36 deletions xblock/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -955,28 +955,58 @@ def has_support(self, view, functionality):
class XBlock2Mixin:
"""
Mixin with shared implementation for all v2 XBlocks, whether they are
wrappers around a v1 XBlock, or pure v2-only XBlocks.
keeping backwards compatibility with v1 or not.
Note: check if an XBlock is "v2" using `issubclass(block, XBlock2Mixin)`,
not `issubclass(block, XBlock2)`
"""
has_children: Final = False

def __init__(self, *args, **kwargs):
"""
Validation during init
"""
super().__init__(*args, **kwargs)
if self.has_children is not False:
raise ValueError('v2 XBlocks cannot declare has_children = True')

Check warning on line 971 in xblock/core.py

View check run for this annotation

Codecov / codecov/patch

xblock/core.py#L969-L971

Added lines #L969 - L971 were not covered by tests

@contextmanager
def _track_field_writes(self, field_updates):
if not isinstance(self, XBlock2Mixin):
raise TypeError("track_field_writes() is only compatible with XBlock2 instances")
if self._dirty_fields:
raise ValueError("Found dirty fields before handler even started - shouldn't happen")
print("Starting handler...")
try:
yield
for field in self._dirty_fields.keys():
scope_type = "user" if field.scope.user != UserScope.NONE else "content"
field_updates["updated_fields"][scope_type][field.name] = field.to_json(getattr(self, field.name))
print("success, dirty fields: ", self._dirty_fields)
print("success, dirty fields: ", field_updates["updated_fields"])
print(f"{self}")
self.force_save_fields([field.name for field in self._dirty_fields.keys()])
self.runtime.save_block(self)

Check warning on line 989 in xblock/core.py

View check run for this annotation

Codecov / codecov/patch

xblock/core.py#L975-L989

Added lines #L975 - L989 were not covered by tests
finally:
self._dirty_fields.clear()
print("Ending handler...")

Check warning on line 992 in xblock/core.py

View check run for this annotation

Codecov / codecov/patch

xblock/core.py#L991-L992

Added lines #L991 - L992 were not covered by tests


class XBlock2(XBlock2Mixin, XBlock):
"""
Base class for pure "v2" XBlocks, that don't need backwards compatibility with v1
"""

def __init__(
self,
runtime,
field_data=None,
scope_ids=UNSET,
for_parent=None,
**kwargs):
**kwargs,
):
"""
Arguments:
runtime (:class:`.Runtime`): Use it to access the environment.
It is available in XBlock code as ``self.runtime``.
scope_ids (:class:`.ScopeIds`): Identifiers needed to resolve
scopes.
Initialize this v2 XBlock, checking for deprecated usage first
"""
if self.has_children is not False:
raise ValueError('v2 XBlocks cannot declare has_children = True')

Check warning on line 1012 in xblock/core.py

View check run for this annotation

Codecov / codecov/patch

xblock/core.py#L1011-L1012

Added lines #L1011 - L1012 were not covered by tests
Expand Down Expand Up @@ -1014,32 +1044,6 @@ def _parent_block_id(self, value):
if value is not None:
raise ValueError("v2 XBlocks cannot have a parent.")

Check warning on line 1045 in xblock/core.py

View check run for this annotation

Codecov / codecov/patch

xblock/core.py#L1044-L1045

Added lines #L1044 - L1045 were not covered by tests

@contextmanager
def _track_field_writes(self, field_updates):
if not isinstance(self, XBlock2Mixin):
raise TypeError("track_field_writes() is only compatible with XBlock2 instances")
if self._dirty_fields:
raise ValueError("Found dirty fields before handler even started - shouldn't happen")
print("Starting handler...")
try:
yield
for field in self._dirty_fields.keys():
scope_type = "user" if field.scope.user != UserScope.NONE else "content"
field_updates["updated_fields"][scope_type][field.name] = field.to_json(getattr(self, field.name))
print("success, dirty fields: ", self._dirty_fields)
print("success, dirty fields: ", field_updates["updated_fields"])
self.force_save_fields([field.name for field in self._dirty_fields.keys()])
self.runtime.save_block(self)
finally:
self._dirty_fields.clear()
print("Ending handler...")


class XBlock2(XBlock2Mixin, XBlock):
"""
Base class for pure "v2" XBlocks, that don't need backwards compatibility with v1
"""


class XBlockAside(Plugin, Blocklike):
"""
Expand Down

0 comments on commit a56d8db

Please sign in to comment.