U
    ad2<                     @   s   d dl Z d dlZd dlZd dlZd dlmZmZmZ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	d
dddddgZG dd deZdd ZdddZdd ZdS )    N)DictListTupleUnion)MODELS_MODULE_NAME)import_string)CollisionResolvingRunner)SubclassesFinder)RemovedInNextVersionWarningz#from django.core.cache import cachez from django.conf import settingsz.from django.contrib.auth import get_user_modelz!from django.db import transactionzRfrom django.db.models import Avg, Case, Count, F, Max, Min, Prefetch, Q, Sum, Whenz!from django.utils import timezonezfrom django.urls import reversez7from django.db.models import Exists, OuterRef, Subqueryc                   @   s   e Zd ZdS )ObjectImportErrorN)__name__
__module____qualname__ r   r   G/tmp/pip-unpacked-wheel-portabvm/django_extensions/management/shells.pyr   !   s   r   c                 C   sj   t t| d}z:z||td  W W S  tk
rH   |d  Y W S X W n tk
rd   |  Y S X dS )a  
    Retrieve application name from models.py module path

    >>> get_app_name('testapp.models.foo')
    'testapp'

    'testapp' instead of 'some.testapp' for compatibility:
    >>> get_app_name('some.testapp.models.foo')
    'testapp'
    >>> get_app_name('some.models.testapp.models.foo')
    'testapp'
    >>> get_app_name('testapp.foo')
    'testapp'
    >>> get_app_name('some.testapp.foo')
    'testapp'
    .   N)listreversedsplitindexr   
ValueError
IndexError)mod_nameZrpartsr   r   r   get_app_name%   s    r   Fc                 C   s  i }| D ]}t |tr | }z8t |tr|drzt|}W nF tk
r } z(|st|d||f  W Y W qW 5 d}~X Y nX t	dd |j
D s|st|d|  W q|st|d|  |j
D ]}t |tjr|jD ]"}|jp|j}	t|j||	< qt |tjrt|ji i dd	 |jD }
|jD ]}|jpX|j}	z@|jd
krt|
D ]}t|
|||< qpnt|
|j||	< W n8 tk
r } ztt|
 t|W 5 d}~X Y nX qHqܐnztjdtdd t |tr4t|}
|
||dd < |s,t|d|  W qn$t |ttfr@t|dkr@t |d ts|s~t|d|d   W qt |d ttfrVt	dd |d D rVt|d i i |d }
g }|d D ]\}zt|
|||< W n8 tk
r   |st|d||d |f  Y nX | | q|s>t|d|d d!|f  nt |d tr|d d
krt|d i i |d }
t|
D ]}t|
|||< q|st|d|d   nRtt|d i i |d g|d }
|
||d < |s>t|d|d |d f  n$|sXt|d|d |d f  n|sXt|d|  W q tk
r   |st|d|  Y qX q|S )a  
    Import the items in import_directives and return a list of the imported items

    Each item in import_directives should be one of the following forms
        * a tuple like ('module.submodule', ('classname1', 'classname2')), which indicates a 'from module.submodule import classname1, classname2'
        * a tuple like ('module.submodule', 'classname1'), which indicates a 'from module.submodule import classname1'
        * a tuple like ('module.submodule', '*'), which indicates a 'from module.submodule import *'
        * a simple 'module.submodule' which indicates 'import module.submodule'.

    Returns a dict mapping the names to the imported items
    )zfrom zimport zError parsing: %r %sNc                 s   s    | ]}t |tjtjfV  qd S N)
isinstanceastImport
ImportFrom).0bodyr   r   r   	<genexpr>[   s     zimport_items.<locals>.<genexpr>z"Only specify import statements: %rz%sc                 S   s   g | ]
}|j qS r   )name)r    r#   r   r   r   
<listcomp>i   s     z import_items.<locals>.<listcomp>*zuOld style import definitions are deprecated. You should use the new style which is similar to normal Python imports.    )
stacklevelr   r   z	import %sz7Unable to import %r: module name must be of type stringr   c                 s   s   | ]}t |tV  qd S r   )r   str)r    er   r   r   r"      s     z.Unable to import %r from %r: %r does not existfrom %s import %s, zfrom %s import *z9Unable to import %r from %r: names must be of type stringz1Unable to import %r: names must be of type stringzUnable to import %r)"r   r(   strip
startswithr   parse	ExceptionprintERRORallr!   SQL_COLTYPEr   namesasnamer#   	importlibimport_moduler   
__import__moduledirgetattrAttributeErrorImportErrorwarningswarnr
   r   r   tuplelenappendjoin)Zimport_directivesstyle
quiet_loadimported_objects	directivenodeexcr!   r#   r5   Zimported_objectkZimported_namesr   r   r   import_itemsB   s    




$,"""  rK   c                    sj  ddl m ddlm} js$|  ddlm
 dg }t
dg }|| dk}d	t
d	i t
d
i  t
di }i i  fdd	
fdd}fdd}fddfdd}	d}
zddl	m
} d}
W n tk
r
   Y nX |rP	s&td t|	d}| D ]\}}||< q<|
r|s| D ]`\}}|dd }t|j}|ksdd||f krqd|jg  |j | qd|sL|	 D ]x\}}|sqt|j}|krq|D ]F}d||jf krq |jr |jg  |j |j q q|  	sttd|rldnd   |  t
d!drƈ	std" tt	d}| D ]\}}||< qt
d#i }|r	std$ t|	d}| D ]\}}||< qt
d%i }|rf	s<td& t|	d}| D ]\}}||< qRS )'Nr   apps)setup)settings	dont_loadZSHELL_PLUS_DONT_LOADr%   rE   ZSHELL_PLUS_MODEL_ALIASESZSHELL_PLUS_APP_PREFIXESSHELL_PLUS_PRE_IMPORTSc                     s   i } t  D ]\}}t|}|i } |}t |D ]\}d||f krTq>||}|sx|rtd||f }n|}| |g  | | d||f  q>q| S )a  
        Collect dictionary from names to possible models. Model is represented as his full path.
        Name of model can be alias if SHELL_PLUS_MODEL_ALIASES or SHELL_PLUS_APP_PREFIXES is specified for this model.
        This dictionary is used by collision resolver.
        At this phase we can't import any models, because collision resolver can change results.
        :return: Dict[str, List[str]]. Key is name, value is list of full model's path's.
        %s.%sz%s_%s)sorteditemsr   get
setdefaultrB   )Zmodels_to_importapp_modmodelsapp_nameZapp_aliasesprefix
model_namealias)app_prefixesrP   load_modelsmodel_aliasesr   r   &get_dict_from_names_to_possible_models   s     

z>import_objects.<locals>.get_dict_from_names_to_possible_modelsc                     s6   t dg } | r2s"td  t|   d S )NZSHELL_PLUS_SUBCLASSES_IMPORTz# Shell Plus Subclasses Imports)r;   r0   	SQL_TABLEr	   Zcollect_subclasses)Zbase_classes_to_import)perform_automatic_importsrE   rO   rD   r   r   import_subclasses   s
    z)import_objects.<locals>.import_subclassesc                     s   t    } |  dS )z
        Perform collision resolving and imports all models.
        When collisions are resolved we can perform imports and print information's, because it is last phase.
        This function updates imported_objects dictionary.
        N)r   Zrun_collision_resolver)Zmodules_to_models)r`   rb   r   r   import_models   s    z%import_objects.<locals>.import_modelsc                    s   |   D ]\}}g }t|D ]\}}z>td||f  |< ||krN|| n|d||f  W q tk
r } z<drt  dst	d||t
|f  W 5 d}~X Y qX qdstd|d|f  qdS )	a  
        Import elements from given dictionary.
        :param modules_to_classes: dictionary from module name to tuple.
        First element of tuple is model name, second is model alias.
        If both elements are equal than element is imported without alias.
        rR   z
%s (as %s)	tracebackrE   z*Failed to import '%s' from '%s' reason: %sNr*   r+   )rT   rS   r   rB   r=   rU   re   	print_excr0   r1   r(   r3   rC   )Zmodules_to_classesZfull_module_pathrX   Zmodel_labelsr[   r\   r)   )rF   optionsrD   r   r   rb      s"    


z1import_objects.<locals>.perform_automatic_importsc                  3   s(      D ]} | jr| j|  fV  qd S r   )Zget_app_configsZmodels_moduleZ
get_models)ZapprL   r   r   get_apps_and_models
  s    z+import_objects.<locals>.get_apps_and_modelsF)_document_registryTz# Shell Plus User Pre Imports)rE   r   rR   z# Shell Plus Model Imports%sz SKIPPED SHELL_PLUS_DJANGO_IMPORTSz# Shell Plus Django ImportsSHELL_PLUS_IMPORTSz# Shell Plus User ImportsSHELL_PLUS_POST_IMPORTSz# Shell Plus User Post Imports)Zdjango.appsrM   ZdjangorN   readyZdjango.confrO   rU   r;   Zmongoengine.baseri   r=   r0   ra   rK   rT   r   r   r   rV   rB   r   rl   )rg   rD   rN   Zdont_load_cliZdont_load_confZdont_load_any_modelsrQ   rc   rd   rh   Zmongoengineri   ZimportsrJ   vr#   modrY   rW   Z
app_modelsrm   rn   r   )r]   rM   rP   r`   rF   r^   r_   rg   rb   rE   rO   rD   r   import_objects   s    
	


rr   )F)r   re   r>   r6   typingr   r   r   r   Zdjango.apps.configr   Zdjango.utils.module_loadingr   Z%django_extensions.collision_resolversr   Z#django_extensions.import_subclassesr	   Z#django_extensions.utils.deprecationr
   rl   r/   r   r   rK   rr   r   r   r   r   <module>   s,   
l