U
    adH                     @   s.  d 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	m
Z
mZmZ ddlmZmZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZ ddlmZ dZdZdZddddddddddddddgZ ej!dej"dej#dej$d ej%d!ej&d"ej'd#iZ(d$d% Z)G d&d' d'Z*d/d)d*Z+d+d, Z,d-d. Z-dS )0z
modelviz.py - DOT file generator for Django Models

Based on:
  Django model to DOT (Graphviz) converter
  by Antonio Cavedoni <antonio@cavedoni.org>
  Adapted to be used with django-extensions
    N)apps)deletion)
ForeignKeyManyToManyFieldOneToOneFieldRelatedField)OneToOneRelManyToOneRel)GenericRelation)ContextTemplateloader)	force_str)	mark_safe)activatez1.1Python)z'Bas van Oostveen <v.oostveen@gmail.com>zOAntonio Cavedoni <http://cavedoni.com/>Stefano J. Attardi <http://attardi.org/>z(limodou <http://www.donews.net/limodou/>zCarlo C8E Mironz Andre Campos <cahenan@gmail.com>z#Justin Findlay <jfindlay@gmail.com>z&Alexander Houben <alexander@houben.ch>z Joern Hees <gitdev@joernhees.de>z%Kevin Cherepski <cherepski@gmail.com>z&Jose Tomas Tocino <theom3ga@gmail.com>z#Adam Dobrawy <naczelnik@jawnosc.tk>z6Mikkel Munch Mortensen <https://www.detfalskested.dk/>z+Andrzej Bistram <andrzej.bistram@gmail.com>z%Daniel Lipsitt <danlipsitt@gmail.com>z5Tobias Mitterdorfer <tobias.mitterdorfer97@gmail.com>ZredZblueZorangeZgreenZyellowZgreyZpurplec                 C   sZ   | sg S t | tttfr| S d| krFtj| rFdd t|  D S dd | 	dD S )N,c                 S   s   g | ]}|  qS  strip.0er   r   I/tmp/pip-unpacked-wheel-portabvm/django_extensions/management/modelviz.py
<listcomp>E   s     z&parse_file_or_list.<locals>.<listcomp>c                 S   s   g | ]}|  qS r   r   r   r   r   r   r   F   s     )

isinstancelisttuplesetospathisfileopen	readlinessplit)argr   r   r   parse_file_or_list?   s    r&   c                   @   s   e Zd Zdd Zdd Zd0ddZdd	 Zd1ddZdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ ZdS )2
ModelGraphc                 K   sF  g | _ |dd | _|dd| _|dd| _t|dd| _|dd| _|dd| _|d	d| _	|d
d| _
|dd| _|dd| _|dd| _|dd | _| jd k	rt| j t|dd| _t|dd| _|dd| _|d| _|dd| _| jr0dd t D | _n|| _|d| _d S )Ncli_optionsdisable_fieldsFdisable_abstract_fieldsinclude_models all_applicationsZgroup_modelsverbose_namesinheritanceTrelations_as_fieldsrelation_fields_onlysort_fieldslanguageexclude_columnsexclude_modelshide_edge_labelsarrow_shapecolor_code_deletionsc                 S   s   g | ]
}|j qS r   )label)r   appr   r   r   r   f   s     z'ModelGraph.__init__.<locals>.<listcomp>rankdir)graphsgetr(   r)   r*   r&   r+   r-   use_subgraphr.   r/   r0   r1   r2   r3   activate_languager4   r5   r6   r7   r8   r   Zget_app_configs
app_labelsr;   )selfr@   kwargsr   r   r   __init__J   s<    




zModelGraph.__init__c                 C   sx   |    g }| jD ]}|dd |d D  q| jD ]<}|d D ].}|d D ] }|d k	rN|d |krNd|d< qNqBq6d S )Nc                 S   s   g | ]}|d  qS )namer   r   r   r   r   r   p   s     z2ModelGraph.generate_graph_data.<locals>.<listcomp>models	relationstargetF
needs_node)process_appsr<   extend)rA   Znodesgraphmodelrelationr   r   r   generate_graph_datak   s    

zModelGraph.generate_graph_dataFc                 C   s   t j  }|d| j| j| j| j| jd}|rdd | jD }|D ]4}|d D ]&}|	d |d D ]}|	d qfqPqD||d	< n
| j|d	< |S )
Nz%Y-%m-%d %H:%M)Z
created_atr(   r)   r*   r>   r;   c                 S   s   g | ]}|  qS r   )flatten)r   contextr   r   r   r      s     z-ModelGraph.get_graph_data.<locals>.<listcomp>rE   rL   fieldsfieldr<   )
datetimenowstrftimer(   r)   r*   r>   r;   r<   pop)rA   Zas_jsonrT   
graph_datar<   rP   Z
model_dataZ
field_datar   r   r   get_graph_datay   s$    
	


zModelGraph.get_graph_datac              	      s   | j r( jr(t j}| r.| }n j}t j}t t	t
frX|d jj7 }  j|| jt fdd|D t t jdS )Nz ({0})c                 3   s   | ]} j |j kV  qd S N)Zcreation_counter)r   Zabstract_fieldrR   r   r   	<genexpr>   s   z,ModelGraph.add_attributes.<locals>.<genexpr>)rR   rD   r9   typeblankabstractrM   primary_key)r.   verbose_namer   islower
capitalizerD   r\   __name__r   r   r   formatremote_field
field_namer]   anyr   r_   )rA   rR   abstract_fieldsr9   tr   rZ   r   add_attributes   s&    


zModelGraph.add_attributesr,   Nc                 C   s2  | j r(|jr(t|j}| r.| }n|j}t|drn| }| j r^| r^|dd }d	|t|}| j
rxd}t|jjtr|jjdkr|j}qd|jjkr|jjdd\}}	n|jjj}|jj}	t||	}n|jj}|rd		|dd
 |}| ||||}
|
|d kr.| |
d r.|
S d S )Nrelated_query_name_ z{} ({})r,   rA   .   z[{}, color={}]rF   rG   )r.   r`   r   ra   rb   rD   hasattrrk   replacerd   r6   r   re   rL   strr$   _meta	app_labelr   Z	get_modelget_relation_context	use_model)rA   rR   rL   extrascolorr9   rk   target_modelru   
model_name_relr   r   r   add_relation   s4    



zModelGraph.add_relationc                 C   s2   g }|D ]}|dd |j D 7 }qtt|}|S )Nc                 S   s"   g | ]}t |d r|jjr|qS rt   )rq   rt   r^   r   Zabstract_modelr   r   r   r      s   
 z2ModelGraph.get_abstract_models.<locals>.<listcomp>)	__bases__r   r   )rA   	appmodelsabstract_modelsappmodelr   r   r   get_abstract_models   s    
zModelGraph.get_abstract_modelsc                 C   s,   t d|j d|j d|jdd g dS )Nz"%s"z%sz
cluster_%srn   rl   )rD   app_nameZcluster_app_namerE   )r   rD   rr   )rA   r:   r   r   r   get_app_context   s    zModelGraph.get_app_contextc                 C   s0   | j rdd |jjD }ndd |jjD }|S )Nc                 S   s   g | ]}|qS r   r   r   rR   r   r   r   r      s     z6ModelGraph.get_appmodel_attributes.<locals>.<listcomp>c                 S   s   g | ]}t |ts|qS r   )r   r   r   r   r   r   r      s    
)r0   rt   local_fields)rA   r   
attributesr   r   r   get_appmodel_attributes   s    z"ModelGraph.get_appmodel_attributesc                 C   s   dd |j D S )Nc                 S   s$   g | ]}t |d r|jjr|jqS r~   )rq   rt   r^   rc   r   r   r   r   r      s   
 z5ModelGraph.get_appmodel_abstracts.<locals>.<listcomp>)r   )rA   r   r   r   r   get_appmodel_abstracts   s    z!ModelGraph.get_appmodel_abstractsc                 C   sN   ||j dd|j|g g d}| jr>|jjr>t|jj|d< n|d |d< |S )Nrn   rl   )rL   r   rD   Z	abstractsrQ   rF   r9   rD   )
__module__rr   rc   r.   rt   r`   r   )rA   r   appmodel_abstractsrP   r   r   r   get_appmodel_context   s    	zModelGraph.get_appmodel_contextc                 C   sD   g }|j D ]4}t|dr
|jjr
||jj || | q
|S )Nrt   )r   rq   rt   r^   rJ   rQ   get_bases_abstract_fields)rA   cZ_abstract_fieldsr   r   r   r   r     s    
z$ModelGraph.get_bases_abstract_fieldsc                 C   sN   d}|j jrd}|j jrd}|d7 }| jr.d}|jdd|jdd|d	d
dS )Nzmulti-tabler^   proxyz\ninheritancer,   rn   rl   r/   z+[arrowhead=empty, arrowtail=none, dir=both]TZ
target_apprG   r\   rD   r9   ZarrowsrH   )rt   r^   r   r6   r   rr   rc   )rA   r   parentr9   r   r   r   get_inheritance_context  s     z"ModelGraph.get_inheritance_contextc                 C   s   t | }|S rY   )r   
get_models)rA   r:   r   r   r   r   r   !  s    zModelGraph.get_modelsc                 C   s(   |j dd|jt|j|j||ddS )Nrn   rl   Tr   )r   rr   rc   r\   rD   )rA   rz   rR   r9   rx   r   r   r   rv   %  s    zModelGraph.get_relation_contextc                 C   s<   |  }| |s|r"||kr"|S |d | || |S )NrQ   )copy
skip_fieldappendrj   )rA   rR   rL   pkrh   newmodelr   r   r   process_attributes0  s
    zModelGraph.process_attributesc              	   C   sh  | j D ]Z}t|}|sq| |}| |}| |}|| }|D ]}| |jjs\qF| 	|}| 
|}| ||}	| |}
|jj}|r|jjs||
kr|	d | || |
D ]}| ||	||}	q| jr| |	}	|jjD ]}| ||	|}	q|jjD ]}| ||	}	q| jr>|jD ]}| |||	}	q(|d |	 qF|d r| j| qd S )NrQ   rE   )r@   r   Zget_app_configr   r   r   rw   rt   Zobject_namer   r   r   r   r   r^   r   rj   r   r2   sort_model_fieldsr   process_local_fieldsZlocal_many_to_manyprocess_local_many_to_manyr/   r   process_parentr<   )rA   ru   r:   Z	app_graphZ
app_modelsr   r   r   rh   rL   r   r   rR   r   r   r   r   rI   7  s@    









zModelGraph.process_appsc                 C   s   |  }|jds&||ks&| |r*|S d }| jrZt|ttfrZt|j	dd }t
|}t|trv| ||d|}n(t|tr| ||d| j|}nd }|d k	r|d | |S )NZ_ptr_idZ	on_deletez*[arrowhead=none, arrowtail=none, dir=both]z([arrowhead=none, arrowtail={}, dir=both]rF   )r   Zattnameendswithr   r8   r   r   r   getattrre   ON_DELETE_COLORSr=   r}   rd   r7   r   )rA   rR   rL   rh   r   ry   Zfield_on_deleterM   r   r   r   r   c  s6    

   
	zModelGraph.process_local_fieldsc                 C   s   |  }| |r|S d }t|trZt|jjdrv|jjjjrv| 	||d
| j| j}nt|trv| 	||td}|d k	r|d | |S )Nrt   z%[arrowhead={} arrowtail={}, dir=both]z>[style="dotted", arrowhead=normal, arrowtail=normal, dir=both]rF   )r   r   r   r   rq   re   Zthroughrt   Zauto_createdr}   rd   r7   r
   r   r   )rA   rR   rL   r   rM   r   r   r   r     s&    

 
z%ModelGraph.process_local_many_to_manyc                 C   sJ   |  }t|drF| ||}||d krF| |d rF|d | |S )Nrt   rF   rG   )r   rq   r   rw   r   )rA   r   r   rL   r   r|   r   r   r   r     s    
zModelGraph.process_parentc                 C   s$   |  }t|d dd d|d< |S )NrQ   c                 S   s   | d  | d  | d fS )Nr_   rM   r9   r   rZ   r   r   r   <lambda>      z.ModelGraph.sort_model_fields.<locals>.<lambda>)key)r   sorted)rA   rL   r   r   r   r   r     s    zModelGraph.sort_model_fieldsc                 C   sp   | j r4| j D ]&}d|dd }t||r dS q| jrh| jD ]&}d|dd }t||r@ dS q@| j  S )z
        Decide whether to use a model, based on the model name and the lists of
        models to exclude and include.
        z^%s$*z.*TF)r+   rr   researchr5   )rA   r{   Zmodel_patternr   r   r   rw     s    

zModelGraph.use_modelc                 C   sV   | j r2| jr"|jr"|j| j kr"dS |j| j kr2dS | jrRt|tttt	t
tfsRdS dS )NTF)r4   r.   r`   rD   r1   r   r   r   r   r   r   r	   )rA   rR   r   r   r   r     s    zModelGraph.skip_field)F)r,   N)rc   r   __qualname__rC   rN   rX   rj   r}   r   r   r   r   r   r   r   r   rv   r   rI   r   r   r   r   rw   r   r   r   r   r   r'   I   s,   !

'
	,	r'   *django_extensions/graph_models/digraph.dotc                 C   sV   t |trt|}t |ts<t|dr4t |jts<tdt| 	 }|
|}|S )NtemplatezyDefault Django template loader isn't used. This can lead to the incorrect template rendering. Please, check the settings.)r   rs   r   Zget_templater   rq   r   	Exceptionr   rO   render)rW   r   r   dotr   r   r   generate_dot  s    

 
r   c                  O   s   t | |}|  | S rY   )r'   rN   rX   )argsrB   	generatorr   r   r   rN     s    
rN   c                 C   s   t g ||d}|| S )N)r+   r5   )r'   rw   )rL   r+   r5   r   r   r   r   rw     s    rw   )r   ).__doc__rS   r   r   Zdjango.appsr   Zdjango.db.modelsr   Zdjango.db.models.fields.relatedr   r   r   r   Z'django.db.models.fields.reverse_relatedr   r	   Z"django.contrib.contenttypes.fieldsr
   Zdjango.templater   r   r   Zdjango.utils.encodingr   Zdjango.utils.safestringr   Zdjango.utils.translationr   r?   __version____license__
__author__Z__contributors__ZCASCADEZPROTECTZSET_NULLZSET_DEFAULTZSETZ
DO_NOTHINGZRESTRICTr   r&   r'   r   rN   rw   r   r   r   r   <module>   sj   	       
   
