Skip to content

Commit

Permalink
Merge branch 'master' into fix/no-double-preview-button
Browse files Browse the repository at this point in the history
  • Loading branch information
fsbraun authored Mar 5, 2025
2 parents 185e7a6 + bf89036 commit 5e155c0
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 34 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
python-version: '3.11'
cache: 'pip'
- name: Cache dependencies
uses: actions/[email protected].0
uses: actions/[email protected].2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('docs/requirements.txt') }}
Expand All @@ -44,7 +44,7 @@ jobs:
python-version: '3.11'
cache: 'pip'
- name: Cache dependencies
uses: actions/[email protected].0
uses: actions/[email protected].2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('docs/requirements.txt') }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.11']
python-version: ['3.12']
requirements-file: ['dj51_cms41.txt']
cms-version: [
'https://github.com/django-cms/django-cms/archive/develop-4.tar.gz'
Expand Down
5 changes: 4 additions & 1 deletion djangocms_versioning/cms_config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import collections

from cms import __version__ as cms_version
from cms.app_base import CMSAppConfig, CMSAppExtension
from cms.extensions.models import BaseExtension
from cms.models import PageContent, Placeholder
Expand All @@ -22,6 +23,7 @@
from django.utils.encoding import force_str
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
from packaging.version import Version as PackageVersion

from . import indicators
from .admin import VersioningAdminMixin
Expand Down Expand Up @@ -393,6 +395,7 @@ class VersioningCMSConfig(CMSAppConfig):
content_admin_mixin=VersioningCMSPageAdminMixin,
)
]
cms_toolbar_mixin = CMSToolbarVersioningMixin
if PackageVersion(cms_version) < PackageVersion("4.2"):
cms_toolbar_mixin = CMSToolbarVersioningMixin
PageContent.add_to_class("is_editable", is_editable)
PageContent.add_to_class("content_indicator", indicators.content_indicator)
37 changes: 30 additions & 7 deletions djangocms_versioning/cms_toolbars.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from cms.cms_toolbars import (
ADD_PAGE_LANGUAGE_BREAK,
LANGUAGE_MENU_IDENTIFIER,
BasicToolbar,
PageToolbar,
PlaceholderToolbar,
)
Expand Down Expand Up @@ -243,7 +244,7 @@ def _get_published_page_version(self):

return PageContent._original_manager.filter(
page=self.page, language=language, versions__state=PUBLISHED
).first()
).select_related("page").first()

def _add_view_published_button(self):
"""Helper method to add a publish button to the toolbar
Expand Down Expand Up @@ -321,7 +322,6 @@ def populate(self):
self.page_content = self.get_page_content() if self.page else None
self.permissions_activated = get_cms_setting("PERMISSION")

self.override_language_menu()
self.change_admin_menu()
self.add_page_menu()
self.change_language_menu()
Expand Down Expand Up @@ -402,8 +402,9 @@ def change_language_menu(self):
url = add_url_parameters(translation_delete_url, language=code)
on_close = REFRESH_PAGE
if self.toolbar.get_object() == pagecontent and not disabled:
other_content = next((self.page.get_admin_content(lang)for lang in self.page.get_languages()
if lang != pagecontent.language and lang in languages), None)
other_content = next(
(self.page.get_admin_content(lang) for lang in self.page.get_languages()
if lang != pagecontent.language and lang in languages), None)
on_close = get_object_preview_url(other_content)
remove_plugins_menu.add_modal_item(name, url=url, disabled=disabled, on_close=on_close)

Expand Down Expand Up @@ -433,10 +434,31 @@ def change_language_menu(self):
)


class VersioningBasicToolbar(BasicToolbar):
def add_language_menu(self):
"""
Originally did override the default language menu for pages that are versioned.
Now creates the menu from scratch, since VersiongBasicToolbar prevents the
core from creating the too generic default language menu.
"""
if not settings.USE_I18N or not self.request.current_page:
# Only add if no page is shown
super().add_language_menu()
return

language_menu = self.toolbar.get_or_create_menu(
LANGUAGE_MENU_IDENTIFIER, _("Language"), position=-1
)
for code, name in get_language_tuple(self.current_site.pk):
# Get the page content, it could be draft too!
page_content = self.page.get_admin_content(language=code)
if page_content:
url = get_object_preview_url(page_content, code)
language_menu.add_link_item(name, url=url, active=self.current_lang == code)


def replace_toolbar(old, new):
"""Replace `old` toolbar class with `new` class,
while keeping its position in toolbar_pool.
"""
"""Replace `old` toolbar class with `new` class, while keeping its position in toolbar_pool."""
new_name = ".".join((new.__module__, new.__name__))
old_name = ".".join((old.__module__, old.__name__))
toolbar_pool.toolbars = OrderedDict(
Expand All @@ -447,3 +469,4 @@ def replace_toolbar(old, new):

replace_toolbar(PageToolbar, VersioningPageToolbar)
replace_toolbar(PlaceholderToolbar, VersioningToolbar)
replace_toolbar(BasicToolbar, VersioningBasicToolbar)
3 changes: 1 addition & 2 deletions djangocms_versioning/datastructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ def content_types(self):


class PolymorphicVersionableItem(VersionableItem):
"""VersionableItem for use by base polymorphic class
(for example filer.File).
"""VersionableItem for use by base polymorphic class (for example filer.File).
"""

def _get_content_types(self):
Expand Down
5 changes: 5 additions & 0 deletions djangocms_versioning/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def get_for_content(self, content_object):
version = self.get(
object_id=content_object.pk, content_type__in=versionable.content_types
)
version._state.fields_cache["content"] = content_object
content_object._version_cache = version
return version

Expand Down Expand Up @@ -243,7 +244,11 @@ def convert_to_proxy(self):
"""Returns a copy of current Version object, but as an instance
of its correct proxy model"""

cache = self._state.fields_cache
del self._state.fields_cache # Remove cache before creating deep copy
new_obj = copy.deepcopy(self)
new_obj._state.fields_cache = cache # Recover caches
self._state.fields_cache = cache # Recover caches
new_obj.__class__ = self.versionable.version_model_proxy
return new_obj

Expand Down
8 changes: 3 additions & 5 deletions djangocms_versioning/plugin_rendering.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from functools import lru_cache

from cms import __version__ as cms_version
from cms.plugin_rendering import ContentRenderer, StructureRenderer
from cms.utils.placeholder import rescan_placeholders_for_obj
from django.utils.functional import cached_property

from . import versionables
from .constants import DRAFT, PUBLISHED
Expand Down Expand Up @@ -77,12 +77,10 @@ def render_plugin(self, instance, page=None):


class CMSToolbarVersioningMixin:
@property
@lru_cache(16)
@cached_property
def content_renderer(self):
return VersionContentRenderer(request=self.request)

@property
@lru_cache(16)
@cached_property
def structure_renderer(self):
return VersionStructureRenderer(request=self.request)
15 changes: 9 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool.ruff]
exclude = [
extend-exclude = [
".eggs",
".git",
".mypy_cache",
Expand All @@ -13,25 +13,24 @@ exclude = [
line-length = 120

[tool.ruff.lint]
# https://beta.ruff.rs/docs/configuration/
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"C", # flake8-comprehensions
"B", # flake8-bugbear
"Q", # flake8-quotes
"Q", # flake8-quotes
"PLE", # pylint error
"PLR", # pylint refactor
"PLW", # pylint warning
"UP", # pyupgrade
"UP", # pyupgrade
]

ignore = [
extend-ignore = [
"B006", # Do not use mutable data structures for argument defaults
"B011", # tests use assert False
"B019", # Use of `functools.lru_cache` or `functools.cache` on methods can lead to memory leaks
"B019", # Use of `functools.lru_cache` on methods can lead to memory leaks
"B905", # `zip()` without an explicit `strict=` parameter
"C901", # too complex functions
"E402", # module level import not at top of file
Expand All @@ -44,6 +43,10 @@ ignore = [
"UP007", # Use `X | Y` for type annotations
]

# TODO: fix these checks separately
# "E501" - Line too long
# "F401" - Unused imports

[tool.ruff.lint.per-file-ignores]
"__init__.py" = [
"F401" # unused-import
Expand Down
2 changes: 1 addition & 1 deletion tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def test_delete_plugin(self):

with self.login_user_context(self.get_superuser()):
response = self.client.post(endpoint, data)
self.assertEqual(response.status_code, 302)
self.assertIn(response.status_code, (200, 302)) # 302 for django CMS < 5

version = Version.objects.get(pk=version.pk)
self.assertEqual(version.modified, dt)
Expand Down
16 changes: 11 additions & 5 deletions tests/test_integration_with_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from cms.toolbar.toolbar import CMSToolbar
from cms.utils.urlutils import admin_reverse
from django.template import Context
from packaging.version import Version as PackageVersion

from djangocms_versioning import constants
from djangocms_versioning.plugin_rendering import VersionContentRenderer
from djangocms_versioning.plugin_rendering import CMSToolbarVersioningMixin, VersionContentRenderer
from djangocms_versioning.test_utils.factories import (
PageFactory,
PageVersionFactory,
Expand All @@ -18,12 +19,14 @@
)


@skipIf(PackageVersion(cms_version) >= PackageVersion("4.2"), "Toolbar integration not necessary for django CMS 4.2+")
class CMSToolbarTestCase(CMSTestCase):
def test_content_renderer(self):
"""Test that cms.toolbar.toolbar.CMSToolbar.content_renderer
is replaced with a property returning VersionContentRenderer
"""
request = self.get_request("/")
self.assertIn(CMSToolbarVersioningMixin, CMSToolbar.__mro__)
self.assertEqual(
CMSToolbar(request).content_renderer.__class__, VersionContentRenderer
)
Expand All @@ -38,7 +41,6 @@ def test_cmstoolbar_mixin(self):


class PageContentAdminTestCase(CMSTestCase):

def test_get_admin_model_object(self):
"""
PageContent normally won't be able to fetch objects in draft. Test if the RequestToolbarForm
Expand Down Expand Up @@ -70,7 +72,6 @@ def test_get_title_cache(self):


class PageAdminCopyLanguageTestCase(CMSTestCase):

def setUp(self):
self.user = self.get_superuser()
page = PageFactory()
Expand Down Expand Up @@ -276,11 +277,16 @@ def setUp(self):
content__language="fr",
state=constants.ARCHIVED,
)
self.page.languages = "en,fr"
try:
self.page.languages = "en,fr"
except AttributeError:
# The property does not have a setter in django CMS 5+
pass
self.page.save()


@skipIf(cms_version < "4.1.4", "Bug only fixed in django CMS 4.1.4")
@skipIf(PackageVersion(cms_version) < PackageVersion("4.1.4"),
"Bug only fixed in django CMS 4.1.4")
def test_get_admin_url_for_language(self):
"""Regression fixed that made unpublished and archived versions invisible to get_admin_url_for_language
template tag. See: https://github.com/django-cms/django-cms/pull/7967"""
Expand Down
10 changes: 6 additions & 4 deletions tests/test_toolbars.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from cms.toolbar.utils import get_object_edit_url, get_object_preview_url
from cms.utils.urlutils import admin_reverse
from django.contrib.auth.models import Permission
from django.test import override_settings
from django.utils.text import slugify
from packaging.version import Version

Expand Down Expand Up @@ -669,6 +670,7 @@ def test_change_language_menu_page_toolbar_language_selector_version_link(self):
self.assertEqual(de_item.url, de_preview_url)
self.assertEqual(it_item.url, it_preview_url)

@override_settings(USE_I18N=False)
def test_page_toolbar_wo_language_menu(self):
from django.utils.translation import gettext as _

Expand All @@ -681,13 +683,13 @@ def test_page_toolbar_wo_language_menu(self):
user=self.get_superuser(),
)
# Remove language menu from request's toolbar
del request.toolbar.menus[LANGUAGE_MENU_IDENTIFIER]
self.assertNotIn(LANGUAGE_MENU_IDENTIFIER, request.toolbar.menus)

# find VersioningPageToolbar
# find VersioningBasicToolbar
for cls, toolbar in request.toolbar.toolbars.items():
if cls == "djangocms_versioning.cms_toolbars.VersioningPageToolbar":
if cls == "djangocms_versioning.cms_toolbars.VersioningBasicToolbar":
# and call override_language_menu
toolbar.override_language_menu()
toolbar.add_language_menu()
break

language_menu = request.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER, _("Language"))
Expand Down

0 comments on commit 5e155c0

Please sign in to comment.