Skip to content

Commit

Permalink
feat: get_last_publish log for PublishableEntity [FC-0059] (#204)
Browse files Browse the repository at this point in the history
* feat: adds VersioningHelper.last_publish_log property and adds test
  Adds freezegun to the test requirements so we can check published_at dates.
* perf: prefetches fields for VersioningHelper.last_publish_log and adds test
* chore: bumps version to 0.10.1
  • Loading branch information
pomegranited authored Jul 31, 2024
1 parent 01defb1 commit d2e5e3b
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 2 deletions.
2 changes: 1 addition & 1 deletion openedx_learning/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
Open edX Learning ("Learning Core").
"""
__version__ = "0.10.0"
__version__ = "0.10.1"
2 changes: 2 additions & 0 deletions openedx_learning/apps/authoring/components/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ class Component(PublishableEntityMixin): # type: ignore[django-manager-missing]
'publishable_entity__draft__version__componentversion',
'publishable_entity__published__version',
'publishable_entity__published__version__componentversion',
'publishable_entity__published__publish_log_record',
'publishable_entity__published__publish_log_record__publish_log',
)

# This foreign key is technically redundant because we're already locked to
Expand Down
12 changes: 12 additions & 0 deletions openedx_learning/apps/authoring/publishing/model_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,18 @@ def has_unpublished_changes(self):

return draft_version_id != published_version_id

@property
def last_publish_log(self):
"""
Return the most recent PublishLog for this component.
Return None if the component is not published.
"""
pub_entity = self.content_obj.publishable_entity
if hasattr(pub_entity, 'published'):
return pub_entity.published.publish_log_record.publish_log
return None

@property
def versions(self):
"""
Expand Down
3 changes: 3 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ filelock==3.15.4
# -r requirements/ci.txt
# tox
# virtualenv
freezegun==1.5.1
# via -r requirements/quality.txt
grimp==3.4.1
# via
# -r requirements/ci.txt
Expand Down Expand Up @@ -391,6 +393,7 @@ python-dateutil==2.9.0.post0
# via
# -r requirements/quality.txt
# celery
# freezegun
python-slugify==8.0.4
# via
# -r requirements/quality.txt
Expand Down
3 changes: 3 additions & 0 deletions requirements/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ edx-opaque-keys==2.10.0
# via
# -r requirements/test.txt
# edx-drf-extensions
freezegun==1.5.1
# via -r requirements/test.txt
grimp==3.4.1
# via
# -r requirements/test.txt
Expand Down Expand Up @@ -253,6 +255,7 @@ python-dateutil==2.9.0.post0
# via
# -r requirements/test.txt
# celery
# freezegun
python-slugify==8.0.4
# via
# -r requirements/test.txt
Expand Down
3 changes: 3 additions & 0 deletions requirements/quality.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ edx-opaque-keys==2.10.0
# via
# -r requirements/test.txt
# edx-drf-extensions
freezegun==1.5.1
# via -r requirements/test.txt
grimp==3.4.1
# via
# -r requirements/test.txt
Expand Down Expand Up @@ -292,6 +294,7 @@ python-dateutil==2.9.0.post0
# via
# -r requirements/test.txt
# celery
# freezegun
python-slugify==8.0.4
# via
# -r requirements/test.txt
Expand Down
1 change: 1 addition & 0 deletions requirements/test.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ mypy # static type checking
django-stubs # Typing stubs for Django, so it works with mypy
djangorestframework-stubs # Typing stubs for DRF
django-debug-toolbar # provides a debug toolbar for Django
freezegun # Allows tests to mock the output of assorted datetime module functions
3 changes: 3 additions & 0 deletions requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ edx-opaque-keys==2.10.0
# via
# -r requirements/base.txt
# edx-drf-extensions
freezegun==1.5.1
# via -r requirements/test.in
grimp==3.4.1
# via import-linter
idna==3.7
Expand Down Expand Up @@ -198,6 +200,7 @@ python-dateutil==2.9.0.post0
# via
# -r requirements/base.txt
# celery
# freezegun
python-slugify==8.0.4
# via code-annotations
pyyaml==6.0.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def test_component_num_queries(self) -> None:
draft = component.versioning.draft
published = component.versioning.published
assert draft.title == published.title
assert component.versioning.last_publish_log.published_at == self.now


class GetComponentsTestCase(ComponentTestCase):
Expand Down
86 changes: 85 additions & 1 deletion tests/openedx_learning/apps/authoring/components/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@
"""
from datetime import datetime, timezone

from freezegun import freeze_time

from openedx_learning.apps.authoring.components.api import (
create_component_and_version,
get_component,
get_or_create_component_type,
)
from openedx_learning.apps.authoring.components.models import ComponentType
from openedx_learning.apps.authoring.publishing.api import LearningPackage, create_learning_package, publish_all_drafts
from openedx_learning.apps.authoring.publishing.api import (
LearningPackage,
create_learning_package,
create_publishable_entity_version,
publish_all_drafts,
)
from openedx_learning.lib.test_utils import TestCase


Expand Down Expand Up @@ -53,3 +60,80 @@ def test_latest_version(self) -> None:

# Grabbing the list of versions for this component
assert list(component.versioning.versions) == [component_version]

def test_last_publish_log(self):
"""
Test last_publish_log versioning property for published Components.
"""
# This Component will get a couple of Published versions
component_with_changes, _ = create_component_and_version(
self.learning_package.id,
component_type=self.problem_type,
local_key="with_changes",
title="Component with changes v1",
created=self.now,
created_by=None,
)

# This Component will only be Published once.
component_with_no_changes, _ = create_component_and_version(
self.learning_package.id,
component_type=self.problem_type,
local_key="with_no_changes",
title="Component with no changes v1",
created=self.now,
created_by=None,
)

# Publish first time.
published_first_time = datetime(2024, 5, 6, 7, 8, 9, tzinfo=timezone.utc)
with freeze_time(published_first_time):
publish_all_drafts(self.learning_package.id)

# Refetch the entities to get latest versions
component_with_changes = get_component(component_with_changes.pk)
component_with_no_changes = get_component(component_with_no_changes.pk)

# Fetch the most recent PublishLog for these components
first_publish_log_for_component_with_changes = component_with_changes.versioning.last_publish_log
first_publish_log_for_component_with_no_changes = component_with_no_changes.versioning.last_publish_log

# PublishLog for library + both entities should match each other
assert (
published_first_time ==
first_publish_log_for_component_with_changes.published_at ==
first_publish_log_for_component_with_no_changes.published_at
)

# Modify component_with_changes
create_publishable_entity_version(
component_with_changes.publishable_entity.id,
version_num=2,
title="Component with changes v2",
created=self.now,
created_by=None,
)

# Publish second time
published_second_time = datetime(2024, 5, 6, 7, 8, 9, tzinfo=timezone.utc)
with freeze_time(published_second_time):
publish_all_drafts(self.learning_package.id)

# Refetch the entities to get latest versions
component_with_changes = get_component(component_with_changes.pk)
component_with_no_changes = get_component(component_with_no_changes.pk)

# Re-fetch the most recent PublishLog for these components
next_publish_log_for_component_with_changes = component_with_changes.versioning.last_publish_log
next_publish_log_for_component_with_no_changes = component_with_no_changes.versioning.last_publish_log

# PublishLog for component_with_changes should have been updated
assert (
published_second_time ==
next_publish_log_for_component_with_changes.published_at
)
# But the component_with_no_changes should still be on the original publish log
assert (
first_publish_log_for_component_with_no_changes ==
next_publish_log_for_component_with_no_changes
)

0 comments on commit d2e5e3b

Please sign in to comment.