U
    ad]9                     @   s   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mZ d dl	m
Z
 d dlmZmZ d dlmZ zd dlZdZW n ek
r   dZY nX z2zd dlZW n ek
r   d dlZY nX dZW n ek
r   dZY nX G d	d
 d
eZdS )    N)settings)BaseCommandCommandError)loader)
ModelGraphgenerate_dot)signalcommandTFc                       s\   e Zd ZdZdZ fddZdd Zedd Zdd
dZ	dddZ
dd Zdd Z  ZS )CommandzCreates a GraphViz dot file for the specified app names. You can pass multiple app names and they will all be combined into a single model. Output is usually directed to a dot file.Tc              $      s  dddddddddddddd	dddd
ddddddddddddddddddddddddddddddddddddddddddd d!ddd"d#ddd$d%ddd&d'ddd(d)d*dd+dd)d,dd+d(d-d.dddd/d0dd+d(d1d2dddd3d4dddd5d6d7d8d9d:dd;d<d=d>d?gd@dAdddBdCdddDdEdDdFdGdHgdIdAdJ| _ ttdKdL}|r| j D ]B}|dM}|dN dOdOdP}||krd|| | j | dQ< qdt j|| dLS )Ra  
        Allow defaults for arguments to be set in settings.GRAPH_MODELS.

        Each argument in self.arguments is a dict where the key is the
        space-separated args and the value is our kwarg dict.

        The default from settings is keyed as the long arg name with '--'
        removed and any '-' replaced by '_'. For example, the default value for
        --disable-fields can be set in settings.GRAPH_MODELS['disable_fields'].
        
store_trueF
pygraphvizz,Output graph data as image using PyGraphViz.)actiondefaultdesthelppydotz-Output graph data as image using PyDot(Plus).dotzDOutput graph data as raw DOT (graph description language) text data.jsonzOutput graph data as JSONZdisable_fieldsz#Do not show the class member fieldsZdisable_abstract_fieldsz7Do not show the class member fields that were inheritedZgroup_modelsz5Group models together respective to their applicationall_applicationsz:Automatically include all applications from INSTALLED_APPSstore
outputfileziRender output file. Type of output dependend on file extensions. Use png or jpg to render graph to image.)r   r   r   layoutzaLayout to be used by GraphViz for visualization. Layouts: circo dot fdp neato nop nop1 nop2 twopi)r   r   r   r   themeZ
django2018zTheme to use. Supplied are 'original' and 'django2018'. You can create your own by creating dot templates in 'django_extentions/graph_models/themename/' template directory.Zverbose_namesz%Use verbose_name of models and fieldslanguagez3Specify language used for verbose_name localizationZexclude_columnszPExclude specific column(s) from the graph. Can also load exclude list from file.Zexclude_modelszjExclude specific model(s) from the graph. Can also load exclude list from file. Wildcards (*) are allowed.Zinclude_modelszBRestrict the graph to specified models. Wildcards (*) are allowed.TZinheritancez$Include inheritance arrows (default)store_falsez!Do not include inheritance arrowsZrelations_as_fieldsz-Do not show relations as fields in the graph.Zrelation_fields_onlyz3Only display fields that are relevant for relationsZsort_fieldszDo not sort fieldsZhide_edge_labelsz*Do not show relations labels in the graph.Zarrow_shapeZboxZcrowZcurveZicurveZdiamondinvnonenormalteeZveezArrow shape to use for relations. Default is dot. Available shapes: box, crow, curve, icurve, diamond, dot, inv, none, normal, tee, vee.)r   r   r   choicesr   Zcolor_code_deletionszColor the relations according to their on_delete setting, where it it applicable. The colors are: red (CASCADE), orange (SET_NULL), green (SET_DEFAULT), yellow (SET), blue (PROTECT), grey (DO_NOTHING) and purple (RESTRICT).TBrankdirZBTZLRZRLzSet direction of graph layout. Supported directions: "TB", "LR", "BT", "RL", corresponding to directed graphs drawn from top to bottom, from left to right, from bottom to top, and from right to left, respectively. Default is TB.)z--pygraphvizz--pydotz--dotz--jsonz--disable-fields -dz--disable-abstract-fieldsz--group-models -gz--all-applications -az--output -oz--layout -lz
--theme -tz--verbose-names -nz--language -Lz--exclude-columns -xz--exclude-models -Xz--include-models -Iz--inheritance -ez--no-inheritance -Ez--hide-relations-from-fields -Rz--relation-fields-onlyz--disable-sort-fields -Sz--hide-edge-labelsz--arrow-shapez--color-code-deletionsz	--rankdirGRAPH_MODELSN r   -_r   )	argumentsgetattrr   splitlstripreplacesuper__init__)selfargskwargsdefaultsargumentZ	arg_splitZsetting_opt	__class__ V/tmp/pip-unpacked-wheel-portabvm/django_extensions/management/commands/graph_models.pyr+   #   s
   
  


zCommand.__init__c                 C   s6   |j ddd | jD ]}|j |d| j|  qdS )z/Unpack self.arguments for parser.add_arguments.	app_label*)nargsr"   N)add_argumentr%   r'   )r,   parserr0   r3   r3   r4   add_arguments   s    
zCommand.add_argumentsc                    s  |d }|s8|d s8t tdi d}|r0|}ntd|dpDd}tj|\}}| }dd	d
dg  fdd| D }t	|
 }|dkrtdddd  D  |dkrtdd | D }	nF|sd}	n<|dkrd}	n.|dkrd
}	n trd	}	ntrd}	ntd|ddkr8|	dkr8td|	dkrP|sPtddtjdd  }
t|fd |
i|}|  |	d
kr|jd!d"}| ||S |jd#d"}|d$ }tjd%d&|d'}t|}t||d(}|	d	kr| j|f|S |	dkr| j|f|S | || d S ))Nr5   r   r!   Z
app_labelsz&need one or more arguments for appnamer    r   r   r   r   c                    s   i | ]\}}| kr||qS r3   r3   ).0kvZoutput_opts_namesr3   r4   
<dictcomp>   s       z"Command.handle.<locals>.<dictcomp>   zOnly one of %s can be set.z, c                 S   s   g | ]}d | qS )z--%sr3   )r<   optr3   r3   r4   
<listcomp>   s     z"Command.handle.<locals>.<listcomp>c                 s   s   | ]\}}|r|V  qd S Nr3   )r<   keyvalr3   r3   r4   	<genexpr>   s      z!Command.handle.<locals>.<genexpr>z.dotz.jsonzNeither pygraphviz nor pydotplus could be found to generate the image. To generate text output, use the --json or --dot options.r    r   )r   r   r   z7--rankdir is not supported for the chosen output format)r   r   zQAn output file (--output) must be specified when --pydot or --pygraphviz are set.r"      cli_optionsT)Zas_jsonFr   Zdjango_extensionsgraph_modelszdigraph.dot)template)r&   r   getr   ospathsplitextloweritemssumvaluesjoinnextHAS_PYGRAPHVIZ	HAS_PYDOTsysargvr   Zgenerate_graph_dataZget_graph_datarender_output_jsonr   Zget_templater   render_output_pygraphvizrender_output_pydotprint_output)r,   r-   optionsZdefault_app_labelsr   r$   Zoutputfile_extZoutput_optsZoutput_opts_countoutputrI   rJ   
graph_datar   Ztemplate_namerK   dotdatar3   r?   r4   handle   s^    



zCommand.handleNc              	   C   sH   t |tr| }|r8t|d}|| W 5 Q R X n| j| dS )z8Write model data to file or stdout in DOT (text) format.wtN)
isinstancebytesdecodeopenwritestdout)r,   ra   output_fileZdot_output_fr3   r3   r4   r]     s    
zCommand.print_outputc              	   C   s>   |r(t |d}t|| W 5 Q R X n| jt| dS )z2Write model data to file or stdout in JSON format.rc   N)rg   r   dumpri   rh   dumps)r,   r`   rj   Zjson_output_fr3   r3   r4   rZ   &  s    zCommand.render_output_jsonc                 K   s   t stdtjd}zBtdd |dD dk rXt }|	| |
d |j}W n tk
rn   Y nX t|}|j|d d	 ||d
  dS )z,Render model data as image using pygraphviz.z,You need to install pygraphviz python modulez-svnc                 s   s   | ]}t |V  qd S rD   )int)r<   r>   r3   r3   r4   rG   5  s     z3Command.render_output_pygraphviz.<locals>.<genexpr>.)r   $   r   r   )progr   N)rV   r   r   __version__rstriptupler'   tempfileNamedTemporaryFilerh   seekname
ValueErrorZAGraphr   Zdraw)r,   ra   r.   versionZtmpfilegraphr3   r3   r4   r[   .  s    



z Command.render_output_pygraphvizc              )   K   s   t stdt|}|s"tdt|ttfrPt|dkrHtj	
d |d }|d }ddd	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/g)}||d0d d1 }||kr|nd2}|j
||d3 d1S )4z'Render model data as image using pydot.z'You need to install pydot python modulezpydot returned an errorrA   z9Found more then one graph, rendering only the first one.
r   r   ZbmpZcanonZcmapZcmapxZcmapx_npr   ZdiaZemfemZfplusZepsZfiggdZgd2ZgifgvimapZimap_npismapZjpeZjpegZjpgZmetafileZpdfZpicplainz	plain-extZpngZpovZpsZps2svgZsvgzZtifZtiffZtkZvmlZvmlzZvrmlZwbmpZxdotrn   Nraw)format)rW   r   r   Zgraph_from_dot_datard   listrs   lenrX   stderrrh   rfind)r,   ra   r.   rz   rj   formatsextZformat_r3   r3   r4   r\   B  sn    
                                    zCommand.render_output_pydot)N)N)__name__
__module____qualname__r   Zcan_import_settingsr+   r:   r   rb   r]   rZ   r[   r\   __classcell__r3   r3   r1   r4   r	      s    -
E

r	   )rX   r   rM   rt   Zdjango.confr   Zdjango.core.management.baser   r   Zdjango.templater   Z%django_extensions.management.modelvizr   r   Z"django_extensions.management.utilsr   r   rV   ImportErrorZ	pydotplusr   rW   r	   r3   r3   r3   r4   <module>   s,   

