a
    Dg                     @   s  d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z" d dl#m$Z$ g dZ%G dd de&Z'G dd de'dZ(G dd dZ)G dd de'Z*G dd de
j+Z,G dd de
j-Z.edd d!d" Z/d#d$ Z0d%d& Z1e(d'iZ2dS )(    N)	lru_cache)import_module)forms)checks)ImproperlyConfiguredrender_to_string	force_str)cached_property)format_html)	mark_safe)capfirst)versioned_static)accepts_kwarg)	JSContext)RemovedInWagtail70Warning)template_is_overridden)	BaseBlockBlock
BoundBlockDeclarativeSubBlocksMetaclassBlockWidget
BlockFieldc                       s   e Zd Z fddZ  ZS )r   c                    sZ   | dd }t | |||}|gdd |D  }ttt|}tt|d |i |_|S )NMetac                 S   s   g | ]}t |d dqS )_meta_classN)getattr).0base r   R/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/wagtail/blocks/base.py
<listcomp>/   s   z%BaseBlock.__new__.<locals>.<listcomp>)	popsuper__new__tuplefilterbooltypestrr   )mcsnamebasesattrsZ
meta_classclsZmeta_class_bases	__class__r   r    r$   )   s    
zBaseBlock.__new__)__name__
__module____qualname__r$   __classcell__r   r   r/   r    r   (   s   r   c                       s  e Zd ZdZdZi ZdZdZG dd dZg Z	 fddZ
d	d
 Zedd Zdd Zdd Zdd Zdd ZdRddZdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% ZdSd&d'ZdTd(d)ZdUd*d+ZdVd,d-ZdWd.d/Zd0d1 Ze d2d3 Z!e d4d5 Z"d6d7 Z#dXd8d9Z$dYd:d;Z%d<d= Z&d>d? Z'd@dA Z(dBdC Z)dDdE Z*dFdG Z+e,dHdI Z-e dJdK Z.dLdM Z/dNdO Z0dPdQ Z1  Z2S )Zr    r   valuez%wagtailcore/shared/block_preview.htmlc                   @   s   e Zd ZdZdZdZdZdS )z
Block.MetaNplaceholderr5   )r1   r2   r3   labelZicon	classnamegroupr   r   r   r    r   @   s   r   c                    s   t  | }||f|_|S N)r#   r$   _constructor_args)r.   argskwargsobjr/   r   r    r$   L   s    
zBlock.__new__c                 K   s   d| j d v r0| j d d}| j d d| |  | _| D ]\}}t| j|| qBtj| _t jd7  _d| j | _	| tj
| j	< | jjpd| _d S )Nr9      Zform_classnamezblockdef-%dr5   )r<   r"   
setdefaultr   metaitemssetattrr   creation_counterZdefinition_prefixdefinition_registryr8   )selfr>   r9   attrr6   r   r   r    __init__S   s    
zBlock.__init__c                 O   s   | |i |S )z
        See `wagtail.blocks.definition_lookup.BlockDefinitionLookup`.
        Construct a block instance from the provided arguments, using the given BlockDefinitionLookup
        object to perform any necessary lookups.
        r   )r.   lookupr=   r>   r   r   r    construct_from_lookuph   s    	zBlock.construct_from_lookupc                 C   s(   || _ | jjs$tt|dd| _d S )N_ )r+   rB   r8   r   r
   replace)rG   r+   r   r   r    set_names   s    zBlock.set_namec                 C   s<   |  D ].\}}|| jv r*t| j|| qtd| qdS )aX  
        Update this block's meta options (out of the ones designated as mutable) from the given dict.
        Used by the StreamField constructor to pass on kwargs that are to be handled by the block,
        since the block object has already been created by that point, e.g.:
        body = StreamField(SomeStreamBlock(), max_num=5)
        z/set_meta_options received unexpected option: %rN)rC   MUTABLE_META_ATTRIBUTESrD   rB   	TypeError)rG   optsrH   r6   r   r   r    set_meta_optionsx   s    
zBlock.set_meta_optionsc                 C   s   t d| j d S )Nz%s.value_from_datadict)NotImplementedErrorr0   )rG   datafilesprefixr   r   r    value_from_datadict   s    zBlock.value_from_datadictc                 C   s   ||vS )a  
        Used only for top-level blocks wrapped by BlockWidget (i.e.: typically only StreamBlock)
        to inform ModelForm logic on Django >=1.10.2 whether the field is absent from the form
        submission (and should therefore revert to the field default).
        r   rG   rU   rV   r+   r   r   r    value_omitted_from_data   s    zBlock.value_omitted_from_dataNc                 C   s   t | |||dS )a  
        Return a BoundBlock which represents the association of this block definition with a value
        and a prefix (and optionally, a ValidationError to be rendered).
        BoundBlock primarily exists as a convenience to allow rendering within templates:
        bound_block.render() rather than blockdef.render(value, prefix) which can't be called from
        within a template.
        )rW   errors)r   )rG   r6   rW   r[   r   r   r    bind   s    z
Block.bindc                 C   s   |  t| jddS )a  
        Return this block's default value (conventionally found in self.meta.default),
        converted to the value type expected by this block. This caters for the case
        where that value type is not something that can be expressed statically at
        model definition time (e.g. something like StructValue which incorporates a
        pointer back to the block definition object).
        defaultN)	normalizer   rB   rG   r   r   r    get_default   s    zBlock.get_defaultc                 C   s   |S )ad  
        Validate value and return a cleaned version of it, or throw a ValidationError if validation fails.
        The thrown ValidationError instance will subsequently be passed to render() to display the
        error message; the ValidationError must therefore include all detail necessary to perform that
        rendering, such as identifying the specific child block(s) with errors, in the case of nested
        blocks. (It is suggested that you use the 'params' attribute for this; using error_list /
        error_dict is unreliable because Django tends to hack around with these when nested.)
        r   rG   r6   r   r   r    clean   s    	zBlock.cleanc                 C   s   |S )aT  
        Given a value for any acceptable type for this block (e.g. string or RichText for a RichTextBlock;
        dict or StructValue for a StructBlock), return a value of the block's native type (e.g. RichText
        for RichTextBlock, StructValue for StructBlock). In simple cases this will return the value
        unchanged.
        r   ra   r   r   r    r^      s    zBlock.normalizec                 C   s   |S )a&  
        Convert 'value' from a simple (JSON-serialisable) value to a (possibly complex) Python value to be
        used in the rest of the block API and within front-end templates . In simple cases this might be
        the value itself; alternatively, it might be a 'smart' version of the value which behaves mostly
        like the original value but provides a native HTML rendering when inserted into a template; or it
        might be something totally different (e.g. an image chooser will use the image ID as the clean
        value, and turn this back into an actual image object here).

        For blocks that are usable at the top level of a StreamField, this must also accept any type accepted
        by normalize. (This is because Django calls `Field.to_python` from `Field.clean`.)
        r   ra   r   r   r    	to_python   s    zBlock.to_pythonc                    s    fdd|D S )z
        Apply the to_python conversion to a list of values. The default implementation simply
        iterates over the list; subclasses may optimise this, e.g. by combining database lookups
        into a single query.
        c                    s   g | ]}  |qS r   )rc   )r   r6   r_   r   r    r!          z(Block.bulk_to_python.<locals>.<listcomp>r   )rG   valuesr   r_   r    bulk_to_python   s    zBlock.bulk_to_pythonc                 C   s   |S )za
        The reverse of to_python; convert the python value into JSON-serialisable form.
        r   ra   r   r   r    get_prep_value   s    zBlock.get_prep_valuec                 C   s   |S )a3  
        Convert a python value for this block into a JSON-serialisable representation containing
        all the data needed to present the value in a form field, to be received by the block's
        client-side component. Examples of where this conversion is not trivial include rich text
        (where it needs to be supplied in a format that the editor can process, e.g. ContentState
        for Draftail) and page / image / document choosers (where it needs to include all displayed
        data for the selected item, such as title or thumbnail).
        r   ra   r   r   r    get_form_state   s    	zBlock.get_form_statec                 C   s    |pi }| d|| j|i |S )a*  
        Return a dict of context variables (derived from the block ``value`` and combined with the
        ``parent_context``) to be used as the template context when rendering this value through a
        template. See :ref:`the usage example <streamfield_get_context>` for more details.
        rG   )updateTEMPLATE_VAR)rG   r6   parent_contextcontextr   r   r    get_context   s    zBlock.get_contextc                 C   s   t | jddS )a  
        Return the template to use for rendering the block if specified.
        This method allows for dynamic templates based on the block instance and a given ``value``.
        See :ref:`the usage example <streamfield_get_template>` for more details.
        templateNr   rB   rG   r6   rl   r   r   r    get_template   s    zBlock.get_templatec                 C   s   d|i}t | jdr||d< nt| jj dt | jf i |}|sV| j||dS |du rj| |}n| j|t	|d}t
t||S )a/  
        Return a text rendering of 'value', suitable for display on templates. By default, this will
        use a template (with the passed context, supplemented by the result of get_context) if a
        'template' property is specified on the block, and fall back on render_basic otherwise.
        rl   r6   z@.get_template should accept a 'value' argument as first argumentrl   N)rk   )r   rq   warningswarnr0   r1   r   render_basicrm   dictr   r   )rG   r6   rl   r=   rn   Znew_contextr   r   r    render   s    
zBlock.renderc                 C   s   |pi S )a  
        Return a dict of context variables to be used as the template context
        when rendering the block's preview. The ``value`` argument is the value
        returned by :meth:`get_preview_value`. The ``parent_context`` argument
        contains the following variables:

        - ``request``: The current request object.
        - ``block_def``: The block instance.
        - ``block_class``: The block class.
        - ``bound_block``: A ``BoundBlock`` instance representing the block and its value.

        If :ref:`the global preview template <streamfield_global_preview_template>`
        is used, the block will be rendered as the main content using
        ``{% include_block %}``, which in turn uses :meth:`get_context`. As a
        result, the context returned by this method will be available as the
        ``parent_context`` for ``get_context()`` when the preview is rendered.
        r   )rG   r6   rk   r   r   r    get_preview_context  s    zBlock.get_preview_contextc                 C   s   t | jddp| jS )a  
        Return the template to use for rendering the block's preview. The ``value``
        argument is the value returned by :meth:`get_preview_value`. The ``context``
        argument contains the variables listed for the ``parent_context`` argument
        of :meth:`get_preview_context` above (and not the context returned by that
        method itself).

        Note that the preview template is used to render a complete HTML page of
        the preview, not just an HTML fragment for the block. The method returns
        the ``preview_template`` attribute from the block's options if provided,
        and falls back to
        :ref:`the global preview template <streamfield_global_preview_template>`
        otherwise.

        If the global preview template is used, the block will be rendered as the
        main content using ``{% include_block %}``, which in turn uses
        :meth:`get_template`.
        preview_templateN)r   rB   DEFAULT_PREVIEW_TEMPLATErp   r   r   r    get_preview_template)  s    zBlock.get_preview_templatec                 C   s"   t | jdr| | jjS |  S )ad  
        Return the placeholder value that will be used for rendering the block's
        preview. By default, the value is the ``preview_value`` from the block's
        options if provided, otherwise the ``default`` is used as fallback. This
        method can be overridden to provide a dynamic preview value, such as
        from the database.
        preview_value)hasattrrB   r^   r|   r`   r_   r   r   r    get_preview_valueA  s    zBlock.get_preview_valuec                 C   s   t | jdd d uS )Nr]   ro   r_   r   r   r    _has_defaultM  s    zBlock._has_defaultc                 C   s`   t | jdp| jjtju}t | jdpF| jpF| jjtjupF| jjtju}t| j	d}|p^|o^|S )Nry   r|   Z	templates)
r}   rB   r0   r{   r   r   rx   r~   r   rz   )rG   Zhas_specific_templateZhas_preview_valueZhas_global_templater   r   r    is_previewableQ  s    zBlock.is_previewablec                 C   s   t | jddS )z
        Return the description of the block to be shown to editors as part of the preview.
        For :ref:`field block types <field_block_types>`, it will fall back to
        ``help_text`` if not provided.
        descriptionr5   ro   r_   r   r   r    get_descriptionk  s    zBlock.get_descriptionc                 C   s
   |  |S )zq
        Can be used to customise the API response and defaults to the value returned by get_prep_value.
        )rg   rp   r   r   r    get_api_representations  s    zBlock.get_api_representationc                 C   s   t |S )z
        Return a text rendering of 'value', suitable for display on templates. render() will fall back on
        this if the block does not define a 'template' property.
        r	   rp   r   r   r    ru   y  s    zBlock.render_basicc                 C   s   g S )zt
        Returns a list of strings containing text content within this block to be used in a search engine.
        r   ra   r   r   r    get_searchable_content  s    zBlock.get_searchable_contentc                 C   s   g S r;   r   ra   r   r   r    extract_references  s    zBlock.extract_referencesc                 C   s   |rdS |  |S dS )z
        Given a list of elements from a content path, retrieve the block at that path
        as a BoundBlock object, or None if the path does not correspond to a valid block.
        N)r\   )rG   r6   Zpath_elementsr   r   r    get_block_by_content_path  s    zBlock.get_block_by_content_pathc                 K   s   g S )z
        Hook for the Django system checks framework -
        returns a list of django.core.checks.Error objects indicating validity errors in the block
        r   )rG   r>   r   r   r    check  s    zBlock.checkc              	   K   s
  g }| j s0|tjd| j  d|d| dd d| j v r`|tjd| j  d|d| dd d| j v r|tjd| j  d	|d| dd
 | j r| j d  r|tjd| j  d|d| dd
 |std| j s|tjd| j  d|d| dd
 |S )z
        Helper method called by container blocks as part of the system checks framework,
        to validate that this block's name is a valid identifier.
        (Not called universally, because not all blocks need names)
        zBlock name %r is invalidzBlock name cannot be emptyfieldzwagtailcore.E001)hintr?   idrM   z!Block names cannot contain spaces-z!Block names cannot contain dashes)r?   r   r   z%Block names cannot begin with a digitz^[_a-zA-Z][_a-zA-Z0-9]*$zBlock names should follow standard Python conventions for variable names: alphanumeric and underscores, and cannot begin with a digit)r+   appendr   Errorgetisdigitrematch)rG   r>   r[   r   r   r    _check_name  s^    
	

	

	
	
zBlock._check_namec                 C   s   dS )z
        Return the ID to be used as the 'for' attribute of <label> elements that refer to this block,
        when the given field prefix is in use. Return None if no 'for' attribute should be used.
        Nr   rG   rW   r   r   r    id_for_label  s    zBlock.id_for_labelc                 C   s   dS )a  
        Flag used to determine whether labels for this block should display a 'required' asterisk.
        False by default, since Block does not provide any validation of its own - it's up to subclasses
        to define what required-ness means.
        Fr   r_   r   r   r    required  s    zBlock.requiredc              	   C   sh   | j }| jj}t|}t||s0td||f z|j| j W S  ttfyb   | d|  Y S 0 dS )zi
        Return the module path string that should be used to refer to this block in migrations.
        zCould not find object %s in %s.
Please note that you cannot serialize things like inner classes. Please move the object into the main module body to use migrations.
.N)	r2   r0   r1   r   r}   
ValueErrorDECONSTRUCT_ALIASESAttributeErrorKeyError)rG   module_namer+   moduler   r   r    canonical_module_path  s    
	zBlock.canonical_module_pathc                 C   s   | j | jd | jd fS )Nr   r@   )r   r<   r_   r   r   r    deconstruct  s    zBlock.deconstructc                 C   s   |   S )a	  
        Like `deconstruct`, but with a `wagtail.blocks.definition_lookup.BlockDefinitionLookupBuilder`
        object available so that any block instances within the definition can be added to the lookup
        table to obtain an ID (potentially shared with other matching block definitions, thus reducing
        the overall definition size) to be used in place of the block. The resulting deconstructed form
        returned here can then be restored into a block object using `Block.construct_from_lookup`.
        )r   )rG   rJ   r   r   r    deconstruct_with_lookup
  s    
zBlock.deconstruct_with_lookupc                    sD   t  tsdS j jkoB   koBt fddjD S )a  
        Implement equality on block objects so that two blocks with matching definitions are considered
        equal. Block objects are intended to be immutable with the exception of set_name() and any meta
        attributes identified in MUTABLE_META_ATTRIBUTES, so checking these along with the result of
        deconstruct (which captures the constructor arguments) is sufficient to identify (valid) differences.

        This was implemented as a workaround for a Django <1.9 bug and is quite possibly not used by Wagtail
        any more, but has been retained as it provides a sensible definition of equality (and there's no
        reason to break it).
        Fc                 3   s*   | ]"}t j|d t  j|d kV  qd S r;   ro   )r   rH   otherrG   r   r    	<genexpr>C  s   zBlock.__eq__.<locals>.<genexpr>)
isinstancer   r+   r   allrP   )rG   r   r   r   r    __eq__  s    
zBlock.__eq__)NN)N)NN)N)N)N)N)N)3r1   r2   r3   r+   rE   rF   rj   rz   r   rP   r$   rI   classmethodrK   rO   rS   rX   rZ   r\   r`   rb   r^   rc   rf   rg   rh   rm   rq   rw   rx   r{   r~   r   r   r   r   r   ru   r   r   r   r   r   r   propertyr   r   r   r   r   r4   r   r   r/   r    r   8   sb   





	








=

r   )	metaclassc                   @   sB   e Zd ZdddZdddZdddZdd	 Zd
d Zdd ZdS )r   Nc                 C   s   || _ || _|| _|| _d S r;   )blockr6   rW   r[   )rG   r   r6   rW   r[   r   r   r    rI   K  s    zBoundBlock.__init__c                 C   s   | j j| j|dS )Nrr   r   rw   r6   rG   rl   r   r   r    rw   Q  s    zBoundBlock.renderc                 C   s   | j j| j|dS )a  
        Alias for render; the include_block tag will specifically check for the presence of a method
        with this name. (This is because {% include_block %} is just as likely to be invoked on a bare
        value as a BoundBlock. If we looked for a `render` method instead, we'd run the risk of finding
        an unrelated method that just happened to have that name - for example, when called on a
        PageChooserBlock it could end up calling page.render.
        rr   r   r   r   r   r    render_as_blockT  s    zBoundBlock.render_as_blockc                 C   s   | j | jS r;   )r   r   rW   r_   r   r   r    r   ^  s    zBoundBlock.id_for_labelc                 C   s   | j | jS )z:Render the value according to the block's native renderingr   r_   r   r   r    __str__a  s    zBoundBlock.__str__c                 C   s   d | jjpt| jj| jS )Nz<block {}: {!r}>)formatr   r+   r(   r1   r6   r_   r   r   r    __repr__e  s    zBoundBlock.__repr__)NN)N)N)	r1   r2   r3   rI   rw   r   r   r   r   r   r   r   r    r   J  s   



r   c                       s    e Zd ZdZ fddZ  ZS )r   z
    Metaclass that collects sub-blocks declared on the base classes.
    (cheerfully stolen from https://github.com/django/django/blob/main/django/forms/forms.py)
    c                    s   g }t | D ]4\}}t|tr|||f || || q|jdd d t	||d< t
 | |||}t	 }t|jD ]H}	t|	dr||	j |	j D ]"\}
}|d u r|
|v r||
 qq||_|S )Nc                 S   s
   | d j S )Nr@   )rE   )xr   r   r    <lambda>{  rd   z7DeclarativeSubBlocksMetaclass.__new__.<locals>.<lambda>)keydeclared_blocks)listrC   r   r   r   rO   r"   sortcollectionsOrderedDictr#   r$   reversed__mro__r}   ri   r   __dict__base_blocks)r*   r+   r,   r-   Zcurrent_blocksr   r6   	new_classr   r   rH   r/   r   r    r$   r  s$    


z%DeclarativeSubBlocksMetaclass.__new__)r1   r2   r3   __doc__r$   r4   r   r   r/   r    r   l  s   r   c                       sz   e Zd ZdZd fdd	Zdd Zedd Zed	d
 Zdd Z	dddZ
dddZedd Zdd Zdd Z  ZS )r   zRWraps a block object as a widget so that it can be incorporated into a Django formNc                    s$   t  j|d || _d | _d | _d S )N)r-   )r#   rI   	block_def_js_context_block_json)rG   r   r-   r/   r   r    rI     s    zBlockWidget.__init__c              
   C   sZ   z"t  | _t| j| j| _W n2 tyT } ztd| |W Y d }~n
d }~0 0 d S )Nz,Error while serializing block definition: %s)	r   r   jsondumpspackr   r   	Exceptionr   )rG   er   r   r    _build_block_json  s
    zBlockWidget._build_block_jsonc                 C   s   | j d u r|   | j S r;   )r   r   r_   r   r   r    
js_context  s    
zBlockWidget.js_contextc                 C   s   | j d u r|   | j S r;   )r   r   r_   r   r   r    
block_json  s    
zBlockWidget.block_jsonc                 C   s   | j |S r;   )r   r   r   r   r   r    r     s    zBlockWidget.id_for_labelc           	      C   sP   t | j|}|r2| d }t t|}n
t d }td|| j||dS )Nr   z
                <div id="{id}" data-block data-controller="w-block" data-w-block-data-value="{block_json}" data-w-block-arguments-value="[{value_json},{error_json}]"></div>
            )r   r   
value_json
error_json)r   r   r   rh   as_dataget_error_json_datar   r   )	rG   r+   r6   r-   r[   rendererr   errorr   r   r   r    render_with_errors  s    
zBlockWidget.render_with_errorsc                 C   s   | j |||d |dS )N)r-   r[   r   )r   )rG   r+   r6   r-   r   r   r   r    rw     s    
zBlockWidget.renderc                 C   s,   | j jtjtdtdgdtdgid S )Nz$wagtailadmin/js/telepath/telepath.jsz"wagtailadmin/js/telepath/blocks.jsr   z'wagtailadmin/css/panels/streamfield.css)Zjscss)r   mediar   ZMediar   r_   r   r   r    r     s    
zBlockWidget.mediac                 C   s   | j |||S r;   )r   rX   rY   r   r   r    rX     s    zBlockWidget.value_from_datadictc                 C   s   | j |||S r;   )r   rZ   rY   r   r   r    rZ     s    z#BlockWidget.value_omitted_from_data)N)NNN)NN)r1   r2   r3   r   rI   r   r   r   r   r   r   rw   r   r   rX   rZ   r4   r   r   r/   r    r     s   




r   c                       s2   e Zd ZdZd	 fdd	Zdd Zdd Z  ZS )
r   zVWraps a block object as a form field so that it can be incorporated into a Django formNc                    s@   |d u rt d|| _d|vr*t||d< t jf i | d S )Nz*BlockField was not passed a 'block' objectZwidget)r   r   r   r#   rI   )rG   r   r>   r/   r   r    rI     s    zBlockField.__init__c                 C   s   | j |S r;   )r   rb   ra   r   r   r    rb     s    zBlockField.cleanc                 C   s   | j || j |kS r;   )r   rg   )rG   initial_valueZ
data_valuer   r   r    has_changed  s    zBlockField.has_changed)N)r1   r2   r3   r   rI   rb   r   r4   r   r   r/   r    r     s   
r   )maxsizec                   C   s   t ddddS )Nzwagtailadmin/shared/icon.htmlhelpr]   )r+   r9   r   r   r   r   r    get_help_icon  s    
r   c                 C   s    t | dr|  S d| jiS dS )a  
    Translate a ValidationError instance raised against a block (which may potentially be a
    ValidationError subclass specialised for a particular block type) into a JSON-serialisable dict
    consisting of one or both of:
    messages: a list of error message strings to be displayed against the block
    blockErrors: a structure specific to the block type, containing further error objects in this
        format to be displayed against this block's children
    as_json_datamessagesN)r}   r   r   )r   r   r   r    r     s    	
r   c                 C   s   t tjdd |  D  S )a  
    Flatten an ErrorList instance containing any number of ValidationErrors
    (which may themselves contain multiple messages) into a list of error message strings.
    This does not consider any other properties of ValidationError other than `message`,
    so should not be used where ValidationError subclasses with nested block errors may be
    present.
    (In terms of StreamBlockValidationError et al: it's valid for use on non_block_errors
    but not block_errors)
    c                 s   s   | ]}|j V  qd S r;   )r   )r   errr   r   r    r     rd   z+get_error_list_json_data.<locals>.<genexpr>)r   	itertoolschainr   )Z
error_listr   r   r    get_error_list_json_data  s    
r   zwagtail.blocks.Block)3r   r   r   r   rs   	functoolsr   	importlibr   Zdjangor   Zdjango.corer   Zdjango.core.exceptionsr   Zdjango.template.loaderr   Zdjango.utils.encodingr
   Zdjango.utils.functionalr   Zdjango.utils.htmlr   Zdjango.utils.safestringr   Zdjango.utils.textr   Zwagtail.admin.staticfilesr   Zwagtail.coreutilsr   Zwagtail.telepathr   Zwagtail.utils.deprecationr   Zwagtail.utils.templatesr   __all__r(   r   r   r   r   ZWidgetr   ZFieldr   r   r   r   r   r   r   r   r    <module>   sJ       "*S
