From 199c1f613822cc33c11cf3e287d753cc6ddf8391 Mon Sep 17 00:00:00 2001 From: Diederik van der Boor Date: Wed, 25 Mar 2015 19:41:41 +0100 Subject: [PATCH] Backwards incompatible: remove collecting import from fluent_pages.integration.fluent_contents This turned out to be a really bad idea, forcing projects into debugging various circular import errors. By making sure the admin is NOT importing during a models import, many cross-importing cases are solved. This issue is amplified when projects use FLUENT_PAGES_PARENT_ADMIN_MIXIN/FLUENT_PAGES_CHILD_ADMIN_MIXIN to insert their own admin mixin classes, which could easily issue a module scan. The prominent example is django-guardian's admin calling get_user_model() --- CHANGES.rst | 3 +++ docs/api/integration/fluent_contents.rst | 8 +++---- docs/newpagetypes/fluent_contents.rst | 8 +++---- fluent_pages/integration/__init__.py | 10 ++++++++ .../integration/fluent_contents/__init__.py | 24 ++++++++++--------- fluent_pages/pagetypes/fluentpage/admin.py | 2 +- fluent_pages/pagetypes/fluentpage/models.py | 2 +- .../pagetypes/fluentpage/page_type_plugins.py | 2 +- 8 files changed, 37 insertions(+), 22 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 04c7b07c..ae182893 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,9 @@ Changes in version 0.9 (dev) * Fix behavior of ``Page.objects.language(..).get_for_path()`` and ``best_match_for_path()``, use the currently selected language. This is similar to django-parler_'s ``TranslatableModel.objects.language(..).create(..)`` support. * Fix skipping mount-points in ``app_reverse()`` when the root is not translated. +* *Backwards incompatible* with previous beta releases: split the ``fluent_pages.integration.fluent_contents`` package. + You'll need to import from the ``.models.``, ``.admin`` and ``.page_type_plugins`` explicitly. + This removes many cases where projects suffered from circular import errors. Released in 0.9c1: diff --git a/docs/api/integration/fluent_contents.rst b/docs/api/integration/fluent_contents.rst index 5e7046f3..dc8e4d81 100644 --- a/docs/api/integration/fluent_contents.rst +++ b/docs/api/integration/fluent_contents.rst @@ -6,19 +6,19 @@ fluent_pages.integration.fluent_contents .. automodule:: fluent_pages.integration.fluent_contents The ``FluentContentsPageAdmin`` class --------------------------------------- +------------------------------------- -.. autoclass:: fluent_pages.integration.fluent_contents.FluentContentsPageAdmin +.. autoclass:: fluent_pages.integration.fluent_contents.admin.FluentContentsPageAdmin :members: The ``FluentContentsPage`` class -------------------------------- -.. autoclass:: fluent_pages.integration.fluent_contents.FluentContentsPage +.. autoclass:: fluent_pages.integration.fluent_contents.models.FluentContentsPage :members: The ``FluentContentsPagePlugin`` class -------------------------------------- -.. autoclass:: fluent_pages.integration.fluent_contents.FluentContentsPagePlugin +.. autoclass:: fluent_pages.integration.fluent_contents.page_type_plugins.FluentContentsPagePlugin :members: diff --git a/docs/newpagetypes/fluent_contents.rst b/docs/newpagetypes/fluent_contents.rst index 24713725..bb9fc150 100644 --- a/docs/newpagetypes/fluent_contents.rst +++ b/docs/newpagetypes/fluent_contents.rst @@ -6,7 +6,7 @@ Integration with fluent-contents The bundled :ref:`fluent page type ` provides a page type where parts of the page can be filled with flexible content blocks. This feature can be used in your custom page types as well. -The :mod:`fluent_pages.integration.fluent_contents` package contains +The :mod:`fluent_pages.integration.fluent_contents` package provides all classes to make this integration painless. .. note:: @@ -32,7 +32,7 @@ This allowed editing the opening view, and "thank you view" as 2 separate area's .. code-block:: python - from fluent_pages.integration.fluent_contents import FluentContentsPage + from fluent_pages.integration.fluent_contents.models import FluentContentsPage class DonationPage(FluentContentsPage): """ @@ -48,7 +48,7 @@ This allowed editing the opening view, and "thank you view" as 2 separate area's .. code-block:: python - from fluent_pages.integration.fluent_contents import FluentContentsPageAdmin + from fluent_pages.integration.fluent_contents.admin import FluentContentsPageAdmin class DonationPageAdmin(FluentContentsPageAdmin): """ @@ -65,7 +65,7 @@ This allowed editing the opening view, and "thank you view" as 2 separate area's from django.conf.urls import url from fluent_pages.extensions import page_type_pool - from fluent_pages.integration.fluent_contents import FluentContentsPagePlugin + from fluent_pages.integration.fluent_contents.page_type_plugins import FluentContentsPagePlugin from .admin import DonationPageAdmin from .models import DonationPage from .views import DonationSuccessView diff --git a/fluent_pages/integration/__init__.py b/fluent_pages/integration/__init__.py index e69de29b..70b24748 100644 --- a/fluent_pages/integration/__init__.py +++ b/fluent_pages/integration/__init__.py @@ -0,0 +1,10 @@ +# import apipkg +# +# realmodule = "fluent_pages.integration._fluent_contents" +# apipkg.initpkg(__name__, { +# 'fluent_contents': { +# 'FluentContentsPage': realmodule + ".models.FluentContentsPage", +# 'FluentContentsPageAdmin': realmodule + ".admin.FluentContentsPageAdmin", +# 'FluentContentsPagePlugin': realmodule + ".admin.FluentContentsPagePlugin", +# } +# }) diff --git a/fluent_pages/integration/fluent_contents/__init__.py b/fluent_pages/integration/fluent_contents/__init__.py index 5d59ff23..a66851bf 100644 --- a/fluent_pages/integration/fluent_contents/__init__.py +++ b/fluent_pages/integration/fluent_contents/__init__.py @@ -7,16 +7,18 @@ The following parts are provided: -* The admin class; :class:`FluentContentsPageAdmin` -* The page type model: :class:`FluentContentsPage` -* The plugin class: :class:`FluentContentsPagePlugin` +* The admin class; :class:`.admin.FluentContentsPageAdmin` +* The page type model: :class:`.models.FluentContentsPage` +* The plugin class: :class:`.page_type_plugins.FluentContentsPagePlugin` + +These classes can be imported from their respective subpackages:: + + from fluent_pages.integration.fluent_contents.admin import FluentContentsPageAdmin + from fluent_pages.integration.fluent_contents.models import FluentContentsPage + from fluent_pages.integration.fluent_contents.page_type_plugins import FluentContentsPagePlugin """ -from .models import FluentContentsPage -from .admin import FluentContentsPageAdmin -from .page_type_plugins import FluentContentsPagePlugin -__all__ = ( - 'FluentContentsPageAdmin', - 'FluentContentsPage', - 'FluentContentsPagePlugin', -) +# There used to be more imports here, but that turned out to be a really bad idea. +# Exposing the model, plugin and admin in one __init__ package means importing the admin, +# and potentially triggering circular imports because of that (e.g. get_user_model(), load all apps) +from .models import FluentContentsPage diff --git a/fluent_pages/pagetypes/fluentpage/admin.py b/fluent_pages/pagetypes/fluentpage/admin.py index feb51937..9b5da2ff 100644 --- a/fluent_pages/pagetypes/fluentpage/admin.py +++ b/fluent_pages/pagetypes/fluentpage/admin.py @@ -1,6 +1,6 @@ from django.conf.urls import url, patterns from fluent_pages.admin import HtmlPageAdmin, PageAdminForm -from fluent_pages.integration.fluent_contents import FluentContentsPageAdmin +from fluent_pages.integration.fluent_contents.admin import FluentContentsPageAdmin from fluent_pages.models import PageLayout from fluent_contents.analyzer import get_template_placeholder_data from fluent_utils.ajax import JsonResponse diff --git a/fluent_pages/pagetypes/fluentpage/models.py b/fluent_pages/pagetypes/fluentpage/models.py index 7fdf3bf2..4ffa9e42 100644 --- a/fluent_pages/pagetypes/fluentpage/models.py +++ b/fluent_pages/pagetypes/fluentpage/models.py @@ -1,7 +1,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from fluent_pages.models import PageLayout -from fluent_pages.integration.fluent_contents import FluentContentsPage +from fluent_pages.integration.fluent_contents.models import FluentContentsPage # This all exists for backwards compatibility diff --git a/fluent_pages/pagetypes/fluentpage/page_type_plugins.py b/fluent_pages/pagetypes/fluentpage/page_type_plugins.py index 2d06d12b..77b98ca4 100644 --- a/fluent_pages/pagetypes/fluentpage/page_type_plugins.py +++ b/fluent_pages/pagetypes/fluentpage/page_type_plugins.py @@ -1,5 +1,5 @@ from fluent_pages.extensions import page_type_pool -from fluent_pages.integration.fluent_contents import FluentContentsPagePlugin +from fluent_pages.integration.fluent_contents.page_type_plugins import FluentContentsPagePlugin from .models import FluentPage from .admin import FluentPageAdmin