
    Bhy                        d dl Z d dlZd dlmZmZ d dlmZ d dlmZm	Z	m
Z
mZ d dlmZ d dlmZmZ d dlmZmZmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZmZ d dlm Z  d dl!m"Z" d dl#m$Z$m%Z& d dl'm(Z( d dl)m*Z* d dl+m,Z,m-Z- d dl.m/Z/ d dl0m1Z1 d dl2m3Z3  G d dejh                        Z5dedefdZ6 G d dejn                  e5      Z8 G d d      Z9y)    N)	lru_cachewraps)
attrgetter)CallableOptionalTypeVarcast)forms)adminmessages)ImproperlyConfiguredObjectDoesNotExistValidationError)HttpRequestHttpResponse)Context)TemplateResponse)	force_str	smart_str)lazy)escapejs)gettextgettext_lazy)
operations)SubClassNeededError)	CMSPluginPage)get_plugin_tree)
DJANGO_5_1)get_cms_settingc                   "     e Zd ZdZ fdZ xZS )CMSPluginBaseMetaclasszj
    Ensure the CMSPlugin subclasses have sane values and set some defaults if
    they're not given.
    c                    t         |   }|D cg c]  }t        |t              s| }}|s || |||      S  || |||      }t	        |j
                  t              st        d|j
                  d|d      t        |d      st        |d      st        d      |j                  sG|j
                  dd}d	t        d	t        f|      i}	t        d
|z  t        j                  f|	      |_
        |j                  sg }
g }|j
                  j                   j"                  D ]_  }|j$                  r|j&                  st        |d      r|j)                  |j*                         E|
j)                  |j*                         a |rd d|
ift-        d      |ddfg|_        |j*                  st/        j0                  dd|      |_        d|v rd|_        d|v rd|_        |S c c}w )NzgThe 'model' attribute on CMSPluginBase subclasses must be either CMSPlugin or a subclass of CMSPlugin. z on z is not.render_templateget_render_templatez\CMSPluginBase subclasses must have a render_template attribute or get_render_template method)positionplaceholderlanguageplugin_typepathdepth)modelexcludeMetaz%sFormadvancedfieldszAdvanced options)collapse)r0   classesz([a-z])([A-Z])z\g<1> \g<2> get_extra_placeholder_menu_itemsTget_extra_plugin_menu_items)super__new__
isinstancer"   
issubclassr,   r   r   hasattrr   formtypeobjectr
   	ModelForm	fieldsets_metar0   auto_creatededitableappendname_resub!_has_extra_placeholder_menu_items_has_extra_plugin_menu_items)clsrC   basesattrs	super_newbaseparents
new_pluginform_meta_attrs
form_attrsbasic_fieldsadvanced_fieldsf	__class__s                ?/home/dcms/DCMS/lib/python3.12/site-packages/cms/plugin_base.pyr6   zCMSPluginBaseMetaclass.__new__    s   GO	$)VDZ>T-U4VVS$u55sD%7
***I6%S]ScSceoq 
 z#45gjRg>h&n  #))bO !$vy/"JKJ"8d?U__4F
SJO##L O%%++22 4~~!**q*-'..qvv6$++AFF34 Hl34)*S`,ab(
$
  ff%5MJO
 .6;?J8(E16:J3g Ws
   GG)__name__
__module____qualname____doc__r6   __classcell__rU   s   @rV   r"   r"      s    
5 5    r"   methodreturnc                     d| _         | S )a  
    Decorator that enables global caching for methods based on placeholder slots and templates.

    This decorator marks methods that should participate in the CMS's template and slot-based
    caching system. Decorated methods will have their results cached according to the
    configuration specified in CMS_PLACEHOLDER_CONF.

    Args:
        method: The method to be decorated.

    Returns:
        The decorated method with template slot caching enabled.

    Example:
        @template_slot_caching
        def get_child_class_overrides(cls, slot: str, page: Optional[Page] = None, instance: Optional[CMSPlugin] = None):
            # Method implementation...
            pass
    T)_template_slot_caching)r^   s    rV   template_slot_cachingrb   X   s    * %)F!Mr]   c                   $    e Zd ZdZdZ ed      ZdZdZ	 dZ	dZ
dZeZdZ	 dZdZ	 dZdZdZdZdZdZ ed       ZdZdZdZdZ ed	      Z	 dZi Zd5 fd
	Z d Z!e"rd Z#e$d        Z%d Z&e$d        Z'e$e(d6de)e*   de)e   fd              Z+e$e,d5de-de)e*   de)e   de.fd              Z/d Z0d Z1d7 fd	Z2	 	 	 d8de3de)e   de)e-   de)e4   de)e4   de5fdZ6d Z7 fd Z8d! Z9d" Z:d6d#Z;d6d$Z<d6d%Z=d& Z>d' Z?d6 fd(	Z@e$d6d)       ZAe$e,d5de-de)e*   de)e   fd*              ZBe$d6de-de)e*   deCfd+       ZDe$e,	 d9de)e*   de)e   d,e.deCfd-              ZEe$e,d5de-de)e*   de)e   fd.              ZFd/ ZGd0 ZH eIeH      ZHe$d1        ZJe$d2        ZKd3 ZLd4 ZM xZNS ):CMSPluginBasez
    Inherits :class:`django:django.contrib.admin.ModelAdmin` and in most respects behaves like a
    normal subclass.

    Note however that some attributes of ``ModelAdmin`` simply won't make sense in the
    context of a Plugin.
     GenericNz&admin/cms/page/plugin/change_form.htmlFTALWAYS_REFRESH_CONTENTPLUGIN_CACHEc                     |rt         |   | j                  |       d| _        d | _        d | _        d | _        i | _        d | _        y )NF)	r5   __init__r,   object_successfully_changedr'   pagecms_plugin_instance_cms_initial_attributes_operation_token)selfr,   
admin_siterU   s      rV   rj   zCMSPluginBase.__init__  sJ    GTZZ4+0(	#'  (*$ $r]   c                     t        | d      r| j                  |||      }nt        | dd      rt        | dd      }nd }|st        d| j                  z        |S )Nr%   r$   Fz!plugin has no render_template: %s)r9   r%   getattrr   rU   )rp   contextinstancer'   templates        rV   _get_render_templatez"CMSPluginBase._get_render_template  s_    4.///;OHT,e4t%6>HH!"E"VWWr]   c                     t         N)	TypeError)rI   items     rV   __class_getitem__zCMSPluginBase.__class_getitem__+  s    Or]   c                 J    | j                   j                  j                         S ry   )r,   _default_managerall)rI   s    rV   get_render_querysetz!CMSPluginBase.get_render_queryset.  s    yy))--//r]   c                     ||d<   ||d<   |S )a  This method returns the context to be used to render the template
        specified in :attr:`render_template`.

        :param dict context: The context with which the page is rendered.
        :param instance: The instance of your plugin that is rendered.
        :type instance: :class:`cms.models.pluginmodel.CMSPlugin` instance
        :param str placeholder: The name of the placeholder that is rendered.
        :rtype: `dict` or :class:`django.template.Context`

        This method must return a dictionary or an instance of
        :class:`django.template.Context`, which will be used as context to render the
        plugin template.

        By default, this method will add ``instance`` and ``placeholder`` to the
        context, which means for simple plugins, there is no need to overwrite this
        method.

        If you overwrite this method it's recommended to always populate the context
        with default values by calling the render method of the super class::

            def render(self, context, instance, placeholder):
                context = super().render(context, instance, placeholder)
                ...
                return context

        ru   r'    )rp   rt   ru   r'   s       rV   renderzCMSPluginBase.render2  s    6 '
!,r]   c                 b    | j                  ||      ry| j                  ||      }t        |      S )NT)get_require_parentget_parent_classesbool)rI   slotrl   allowed_parentss       rV   requires_parent_pluginz$CMSPluginBase.requires_parent_pluginQ  s2    !!$-00t<O$$r]   rl   ru   c                    |r t        |j                  t                     S |i|j                  j                  rSt        |j                  j                  d      r3 t        |j                  j                  j                  t                     S y)zCache page template because page.get_template() might have to fetch the page content object from the db
        since django CMS 4Nget_template)r   r   strr'   sourcer9   )rI   rl   ru   s      rV   _get_template_for_confz$CMSPluginBase._get_template_for_confY  st    
 /4))3/11 $$++,,33^D G4,,33@@#FHHr]   r   r_   c                 b    ddl m} | j                  ||      } |d||| j                        }|S )Nr   get_placeholder_confrequire_parentdefault)cms.utils.placeholderr   r   r   )rI   r   rl   ru   r   rv   r   s          rV   r   z CMSPluginBase.get_require_parentj  s9     	?--dH= ..>hX[XjXjkr]   c                      y)a  
        Provides hints to the placeholder, and in turn to the page for
        determining the appropriate Cache-Control headers to add to the
        HTTPResponse object.

        :param request: Relevant ``HTTPRequest`` instance.
        :param instance: The ``CMSPlugin`` instance that is being rendered.
        :rtype: ``None`` or ``datetime`` or ``time_delta`` or ``int``

        Must return one of:

        :``None``:
            This means the placeholder and the page will not even
            consider this plugin when calculating the page expiration;

        :``datetime``:
            A specific date and time (timezone-aware) in the future
            when this plugin's content expires;

            .. important:: The returned ``datetime`` must be timezone-aware
                           or the plugin will be ignored (with a warning)
                           during expiration calculations.


        :``datetime.timedelta``:
            A timedelta instance indicating how long, relative to
            the response timestamp that the content can be cached;

        :``int``:
            An integer number of seconds that this plugin's content can be cached.

        There are constants are defined in ``cms.constants`` that may be
        useful: :const:`~cms.constants.EXPIRE_NOW` and :const:`~cms.constants.MAX_EXPIRATION_TTL`.

        An integer value of 0 (zero) or :const:`~cms.constants.EXPIRE_NOW` effectively means "do not
        cache". Negative values will be treated as :const:`~cms.constants.EXPIRE_NOW`. Values exceeding the value
        :const:`~cms.constants.MAX_EXPIRATION_TTL` will be set to that value.

        Negative `timedelta` values or those greater than ``MAX_EXPIRATION_TTL``
        will also be ranged in the same manner.

        Similarly, ``datetime`` values earlier than now will be treated as
        ``EXPIRE_NOW``. Values greater than ``MAX_EXPIRATION_TTL`` seconds in the
        future will be treated as ``MAX_EXPIRATION_TTL`` seconds in the future.
        Nr   rp   requestru   r'   s       rV   get_cache_expirationz"CMSPluginBase.get_cache_expirationu  s    \ r]   c                      y)a  
        Returns an HTTP VARY header string or a list of them to be considered by the placeholder
        and in turn by the page to caching behaviour.

        Overriding this method is optional.

        Must return one of:

        :``None``:
            This means that this plugin declares no headers for the cache
            to be varied upon. (default)

        :string:
            The name of a header to vary caching upon.

        :list of strings:
            A list of strings, each corresponding to a header to vary the
            cache upon.

        .. note::
            This only makes sense to use with caching. If this plugin has
            ``cache = False`` or plugin.get_cache_expiration(...) returns 0,
            get_vary_cache_on() will have no effect.
        Nr   r   s       rV   get_vary_cache_onzCMSPluginBase.get_vary_cache_on  s    2 r]   c                     |j                  d|j                  vd|t        d      d       t        |   ||||||      S )z7
        We just need the popup interface here
        
no_previewT	MEDIA_URL)previewis_popuppluginCMS_MEDIA_URL)updateGETr    r5   render_change_form)rp   r   rt   addchangeform_urlobjrU   s          rV   r   z CMSPluginBase.render_change_form  sM     	'w{{: !0!=		
 w)'7CSVWWr]   r   r   action
extra_dataextra_contextc           
         t        j                  |      D cg c]&  }|j                  |j                  |j                  d( }}s!d||d|xs i d|xs i }t        |d|      S 	 j                  rj                  j                         n}	|	gt        |	j                               z   }
|dv r|
d   nt        fd|
D        d	      }t        ||
|
      }t        fd|d   D        i       }di ||t        t        j                                     ||d|xs i d|xs i }t        |d|      S c c}w # t        $ r }	Y w xY w)a~  
        Renders the close frame for a CMS plugin in the Django admin interface.

        This method is used to send information to the javascript frontend
        after an edit action has taken place. It allows the javascript frontend
        to update the structure and content on the edit endpoints.

        Args:
            request (HttpRequest): The HTTP request object.
            obj (CMSPlugin): The CMS plugin instance being rendered.
            action (Optional[str]): The action being performed on the plugin.
                Defaults to "edit". Possible values are "add", "edit", "move", and "delete".
            extra_data (Optional[Context]): Additional data to include in
                the data bridge to the frontend. Defaults to None.
            extra_context (Optional[Context]): Additional context to include in
                the rendering. Defaults to None.

        Returns:
            HttpResponse: The rendered confirmation form as an HTTP response.

        Raises:
            ObjectDoesNotExist: If the parent plugin is a ghost plugin and the
                plugin tree cannot be fetched.

        Notes:
            - Handles edge cases where the parent plugin is a ghost plugin.
            - Constructs the plugin tree structure and gathers plugin-specific
              data for rendering.
            - Includes messages from the request in the context.
        )levelmessagetagsT)r   r   )r   data_bridgez'admin/cms/page/plugin/confirm_form.html)r   deleter   c              3   V   K   | ]   }|j                   j                   k(  s| " y wry   pk).0r   r   s     rV   	<genexpr>z3CMSPluginBase.render_close_frame.<locals>.<genexpr>  s      K&vyyCFF7JvKs   ))N)target_pluginc              3   H   K   | ]  }|d    j                   k(  s|  yw)	plugin_idNr   )r   plugin_datar   s     rV   r   z3CMSPluginBase.render_close_frame.<locals>.<genexpr>  s%     g[KP[D\`c`f`fDf[gs   ""plugins)r   plugin_desc	structurer   )r   r   r   )r   get_messagesr   r   r   r   parentget_bound_pluginr   listget_descendantsnextr   r   r   get_short_description)rp   r   r   r   r   r   r   dj_messagesrt   rootr   r   r   r   s     `           rV   render_close_framez CMSPluginBase.render_close_frame  s   Z $009
 	 !"??
 
  !$ +  "'R  !&BG $G-VX_``	47JJ3::..0CD &4 4 4 677 ** AJKGKTR 	
 $GWMR	gIi,@gik

  '	#2K2K2M(NO&' #
 "
  )RT[\\u
0 " 	 D	s   +D;*(E   EEc                 \   ddl m} |j                  }|j                  |j                  j                     }||d}|rL| j
                  j                  j                  |j                        |d<   ||d<   t        j                  |d<   n\|j                  r|j                  j                  nd}	|j                  j                  |	      }
||d	<   t        j                  |d<   |
|d
<    |j                  di || _        |j!                  |      | _        |j%                  |j&                         y)z
        Override original method, and add some attributes to obj
        This has to be made, because if the object is newly created, it must know
        where it lives.
        r   )site)r   r'   r   
old_pluginrO   	operationNr   
tree_orderr   )django.contrib.adminr   r'   	_registryrU   r,   objectsgetr   r   CHANGE_PLUGINr   get_plugin_tree_order
ADD_PLUGIN_send_pre_placeholder_operationro   
add_pluginsaved_objectclear_cacher(   )rp   r   r   r:   r   r   plpl_adminoperation_kwargs	parent_idr   s              rV   
save_modelzCMSPluginBase.save_model2  s
    	.__>>#//";";<
 -1ZZ-?-?-C-Csvv-C-N\*-0\*,6,D,D[)),

I>>yIJ),X&,6,A,A[)-7\* H H H \K[ \ MM#.
s||$r]   c                     t         |   |||      }| j                  j                         D ]  \  }}t	        |||        |S ry   )r5   	save_formrn   itemssetattr)rp   r   r:   r   r   fieldvaluerU   s          rV   r   zCMSPluginBase.save_formQ  sK    gv6 88>>@ 	'LE5C&	' 
r]   c                 8    d| _         | j                  ||d      S )NTr   r   )rk   r   )rp   r   r   kwargss       rV   response_addzCMSPluginBase.response_addY  s$    +/(
 &&wE&BBr]   c                    d| _         | j                  j                  }t        |j                        t        |      d}t        d      |z  }| j                  ||t        j                         | j                  ||d      S )NT)rC   r   z0The %(name)s "%(obj)s" was changed successfully.r   r   )
rk   r,   r?   r   verbose_namerD   message_userr   SUCCESSr   )rp   r   r   optsmsg_dictmsgs         rV   response_changezCMSPluginBase.response_changea  sr    +/(zz%d&7&783PBChN'3(8(89&&wH&EEr]   c                      y ry   r   )rp   r   r   bypasss       rV   log_additionzCMSPluginBase.log_additioni      r]   c                      y ry   r   )rp   r   r   r   r   s        rV   
log_changezCMSPluginBase.log_changel  r   r]   c                      y ry   r   )rp   r   r   object_reprr   s        rV   log_deletionzCMSPluginBase.log_deletiono  r   r]   c                      y)al  Deprecated: Since djangocms-text-ckeditor introduced inline previews of plugins, the icon will not be
        rendered in TextPlugins anymore.

        By default, this returns an empty string, which, if left un-overridden would result in no icon
        rendered at all, which, in turn, would render the plugin un-editable by the operator inside a parent
        text plugin.

        Therefore, this should be overridden when the plugin has text_enabled set to True to return the path
        to an icon to display in the text of the text plugin.

        :param instance: The instance of the plugin model.
        :type instance: :class:`cms.models.pluginmodel.CMSPlugin` instance

        Example::

            def icon_src(self, instance):
                return static("cms/img/icons/plugins/link.png")

        See also: :attr:`text_enabled`, :meth:`icon_alt`
        re   r   rp   ru   s     rV   icon_srczCMSPluginBase.icon_srcr  s    * r]   c                 H    t        | j                         dt        |       S )a  
        Overwrite this if necessary if ``text_enabled = True``
        Return the 'alt' text to be used for an icon representing
        the plugin object in a text editor.

        :param instance: The instance of the plugin model to provide specific information
            for the 'alt' text.
        :type instance: :class:`cms.models.pluginmodel.CMSPlugin` instance

        By default, :meth:`icon_alt` will return a string of the form: "[plugin type] -
        [instance]", but can be modified to return anything you like.

        This function accepts the ``instance`` as a parameter and returns a string to be
        used as the ``alt`` text for the plugin's preview or icon.

        Authors of text-enabled plugins should consider overriding this function as
        it will be rendered as a tooltip in most browser. This is useful, because if
        the same plugin is used multiple times, this tooltip can provide information about
        its configuration.

        See also: :attr:`text_enabled`, :meth:`icon_src`.


        z - )r   rC   r   s     rV   icon_altzCMSPluginBase.icon_alt  s%    2 DII&'s9X+>*?@@r]   c                     t         |   ||      }|D ]  \  }}|j                  d      s|c S  | j                  rg S 	 | j	                  |      |d   d   d<   |S # t
        $ r Y |S w xY w)z^
        Same as from base class except if there are no fields, show an info message.
        r0   )r   r      description)r5   get_fieldsetsr   inlinesget_empty_change_form_textKeyError)rp   r   r   r>   rC   datarU   s         rV   r  zCMSPluginBase.get_fieldsets  s     G)'37	# 	!JD$xx!  	! <<I	-1-L-LQT-L-UIaLOM*   		s    A 	A*)A*c                     t        d      S )zv
        Returns the text displayed to the user when editing a plugin
        that requires no configuration.
        zAThere are no further settings for this plugin. Please press save.)r   )rI   r   s     rV   r  z(CMSPluginBase.get_empty_change_form_text  s     Z[[r]   c                     ddl m} | j                  ||      } |d||i       }|j                  | j                  | j
                        S )ze
        Returns a list of plugin types that are allowed
        as children of this plugin.
        r   r   child_classesr   )r   r   r   r   rW   r	  )rI   r   rl   ru   r   rv   ph_confs          rV   get_child_class_overridesz'CMSPluginBase.get_child_class_overrides  sG     	?--dH= 'hPRS{{3<<):):;;r]   c                 6    ddl m} |j                  ||d      S )z
        Returns a list of all plugin classes
        that will be considered when fetching
        all available child classes for this plugin.
        r   )plugin_poolF)root_plugin)cms.plugin_poolr  get_all_plugins)rI   r   rl   r  s       rV   get_child_plugin_candidatesz)CMSPluginBase.get_child_plugin_candidates  s     	0**45*IIr]   only_uncachedc                    | j                  |||      }| j                  ||      }|r)|D cg c]  }|j                  |v s|j                   c}S |r|D cg c]  }|j                  r| }}g }| j                  }|D ]7  }	|	j	                  |||      }
|
r||
v s|j                  |	j                         9 |S c c}w c c}w )zf
        Returns a list of plugin types that can be added
        as children to this plugin.
        )rl   ru   )r  r  rW   cache_parent_classesr   rB   )rI   r   rl   ru   r  r	  installed_pluginsr   r)   plugin_classr   s              rV   get_child_classeszCMSPluginBase.get_child_classes  s     55dPX5Y;;D$G2ChvZgGgFOOhh6G kFvOjOj k kll . 	<L*==dD(SO"k_&D $$\%:%:;	< / i !ls   B<B<C*Cc                     ddl m} | j                  ||      } |d||i       }|j                  | j                  | j
                        }|S )Nr   r   parent_classesr   )r   r   r   r   rW   r  )rI   r   rl   ru   r   rv   r
  r  s           rV   r   z CMSPluginBase.get_parent_classes  sM     	?--dH= ''7xQST S\\33E3EFr]   c                     g S )aU  
        Returns the URL patterns the plugin wants to register views for.
        They are included under django CMS's page admin URLS in the plugin path
        (e.g.: ``/admin/cms/page/plugin/<plugin-name>/`` in the default case).


        ``get_plugin_urls()`` is useful if your plugin needs to talk asynchronously to the admin.
        r   rp   s    rV   get_plugin_urlszCMSPluginBase.get_plugin_urls  s	     	r]   c                 "    | j                         S ry   )r  r  s    rV   plugin_urlszCMSPluginBase.plugin_urls  s    ##%%r]   c                      y)aM  Extends the placeholder context menu for all placeholders.

        To add one or more custom context menu items that are displayed in the context menu for all placeholders when
        in structure mode, override this method in a related plugin to return a list of
        :class:`cms.plugin_base.PluginMenuItem` instances.
        Nr   )rp   r   r'   s      rV   r3   z.CMSPluginBase.get_extra_placeholder_menu_items#       	r]   c                      y)a>  Extends the plugin context menu for all plugins.

        To add one or more custom context menu items that are displayed in the context menu for all plugins when in
        structure mode, override this method in a related plugin to return a list of
        :class:`cms.plugin_base.PluginMenuItem` instances.
        Nr   )rI   r   r   s      rV   r4   z)CMSPluginBase.get_extra_plugin_menu_items-  r   r]   c                 ,    t        | j                        S ry   )r   rC   r  s    rV   __repr__zCMSPluginBase.__repr__7  s    ##r]   c                     | j                   S ry   )rC   r  s    rV   __str__zCMSPluginBase.__str__:  s    yyr]   )NNry   )FFre   N)editNN)NNF)OrW   rX   rY   rZ   rC   rD   moduler:   change_form_templateadmin_previewr$   render_pluginr   r,   text_enabled	page_onlyallow_childrenr	  r   r  disable_child_pluginsdisable_editshow_add_formr    is_localcache_child_classesr  rG   rH   cachesystemr   rj   rw   r   r|   classmethodr   r   r   r   r   r   r   rb   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r   r  r  r   r  r  propertyr3   r4   r#  r%  r[   r\   s   @rV   rd   rd   q   s    D y\F DC M O M EL5" IN. M N N " L M ##;<<H
 (-%#( N+E" FD%
 	 0 0> % % (4. HYDW    c $ RZ[dRe qu   .`6X& !'(,+/a]a] i a] 	a]
 W%a]  (a] 
a]F%>CF.A6& \ \ <S < <YabkYl <  < Js J(4. JTX J J lq%!$%:B9:M%ei%	%  %N c $ RZ[dRe   	& ;'K   $r]   rd   )	metaclassc                       e Zd ZdZddZy)PluginMenuItema  
    Creates an item in the plugin / placeholder menu

    :param name: Item name (label)
    :param url: URL the item points to. This URL will be called using POST
    :param data: Data to be POSTed to the above URL
    :param question: Confirmation text to be shown to the user prior to call the given URL (optional)
    :param action: Custom action to be called on click; currently supported: 'ajax', 'ajax_add'
    :param attributes: Dictionary whose content will be added as data-attributes to the menu item

    Nc                     |si }|rt        j                  |      }|| _        || _        || _        || _        || _        || _        y ry   )jsondumpsrC   urlr  questionr   
attributes)rp   rC   r=  r  r>  r   r?  s          rV   rj   zPluginMenuItem.__init__K  sE    J::d#D		 $r]   )NNajaxN)rW   rX   rY   rZ   rj   r   r]   rV   r9  r9  >  s    
%r]   r9  ):r;  rE   	functoolsr   r   operatorr   typingr   r   r   r	   djangor
   django.contribr   r   django.core.exceptionsr   r   r   django.httpr   r   django.templater   django.template.responser   django.utils.encodingr   r   django.utils.functionalr   django.utils.htmlr   django.utils.translationr   r   rD   cmsr   cms.exceptionsr   
cms.modelsr   r   cms.toolbar.utilsr   cms.utils.compatr   cms.utils.confr    MediaDefiningClassr"   rb   
ModelAdminrd   r9  r   r]   rV   <module>rV     s     	 &  4 4  * \ \ 1 # 5 6 ( & ?  . & - ' *;U55 ;|( x 2JE$$0F JZ% %r]   