3

\Y+                 @   s   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mZmZ d%ddZedddd Zd&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 )'    N)import_module)apps)MODELS_MODULE_NAME)settings)AppRegistryNotReady)	lru_cache)import_string)AppNotFoundErrorClassNotFoundErrorModuleNotFoundError
oscar.appsc             C   s   t | |g|d S )a  
    Dynamically import a single class from the given module.

    This is a simple wrapper around `get_classes` for the case of loading a
    single class.

    Args:
        module_label (str): Module label comprising the app label and the
            module name, separated by a dot.  For example, 'catalogue.forms'.
        classname (str): Name of the class to be imported.

    Returns:
        The requested class object or `None` if it can't be found
    r   )get_classes)module_label	classnamemodule_prefix r   -/var/www/html/oscar2019/oscar/core/loading.py	get_class   s    r   d   )maxsizec               C   s
   t tjS )N)r   r   OSCAR_DYNAMIC_CLASS_LOADERr   r   r   r   get_class_loader"   s    r   c             C   s   t  }|| ||S )N)r   )r   
classnamesr   Zclass_loaderr   r   r   r   '   s    r   c       
      C   s   d| krt dd|| f }t||}t| \}}|jd| rFd}n | j|dd}|| }	t|	|}||  koxdkn  rtd|  t||g|S )	a  
    Dynamically import a list of classes from the given module.

    This works by looping over ``INSTALLED_APPS`` and looking for a match
    against the passed module label.  If the requested class can't be found in
    the matching module, then we attempt to import it from the corresponding
    core app.

    This is very similar to ``django.db.models.get_model`` function for
    dynamically loading models.  This function is more general though as it can
    load any class from the matching app, not just a model.

    Args:
        module_label (str): Module label comprising the app label and the
            module name, separated by a dot.  For example, 'catalogue.forms'.
        classname (str): Name of the class to be imported.

    Returns:
        The requested class object or ``None`` if it can't be found

    Examples:

        Load a single class:

        >>> get_class('dashboard.catalogue.forms', 'ProductForm')
        oscar.apps.dashboard.catalogue.forms.ProductForm

        Load a list of classes:

        >>> get_classes('dashboard.catalogue.forms',
        ...             ['ProductForm', 'StockRecordForm'])
        [oscar.apps.dashboard.catalogue.forms.ProductForm,
         oscar.apps.dashboard.catalogue.forms.StockRecordForm]

    Raises:

        AppNotFoundError: If no app is found in ``INSTALLED_APPS`` that matches
            the passed module label.

        ImportError: If the attempted import of a class raises an
            ``ImportError``, it is re-raised
    .z1Importing from top-level modules is not supportedz%s.%sz%s.N    zThe module with label '%s' could not be imported. This eithermeans that it indeed does not exist, or you might have a problem with a circular import.)
ValueError_import_module_find_installed_apps_entry
startswithreplacer   _pluck_classes)
r   r   r   Zoscar_module_labelZoscar_moduleZinstalled_apps_entryapp_nameZlocal_moduleZ
sub_moduleZlocal_module_labelr   r   r   default_class_loader,   s     ,

r#   c             C   sL   yt | |dS  tk
rF   tj \}}}tj|}t|dkrB Y nX dS )z
    Imports the module with the given name.
    Returns None if the module doesn't exist, but propagates any import errors.
    )fromlistr   N)
__import__ImportErrorsysexc_info	traceback
extract_tblen)r   r   __exc_tracebackframesr   r   r   r      s    
r   c             C   sp   g }xf|D ]^}d}x"| D ]}t ||rt||}P qW |s^dd | D }td|dj|f |j| q
W |S )z
    Gets a list of class names and a list of modules to pick from.
    For each class name, will return the class from the first module that has a
    matching class.
    Nc             S   s   g | ]}|d k	r|j qS )N)__name__).0mr   r   r   
<listcomp>   s    z"_pluck_classes.<locals>.<listcomp>zNo class '%s' found in %sz, )hasattrgetattrr
   joinappend)modulesr   Zklassesr   klassmodulepackagesr   r   r   r!      s    



r!   c             C   s.   x(t jD ]}|| ks"|jd|  r|S qW dS )a  
    Given an app name (e.g. 'catalogue'), walk through INSTALLED_APPS
    and return the first match, or None.
    This does depend on the order of INSTALLED_APPS and will break if
    e.g. 'dashboard.catalogue' comes before 'catalogue' in INSTALLED_APPS.
    r   N)r   INSTALLED_APPSendswith)r"   Zinstalled_appr   r   r   _get_installed_apps_entry   s    r=   c                sX   | j d  fddtdt D }x |D ]}t|}|r,||fS q,W td|  dS )a}  
    Given a module label, finds the best matching INSTALLED_APPS entry.

    This is made trickier by the fact that we don't know what part of the
    module_label is part of the INSTALLED_APPS entry. So we try all possible
    combinations, trying the longer versions first. E.g. for
    'dashboard.catalogue.forms', 'dashboard.catalogue' is attempted before
    'dashboard'
    r   c                s    g | ]}d j  d|  qS )r   N)r5   )r0   count)r7   r   r   r2      s    z._find_installed_apps_entry.<locals>.<listcomp>r   z&Couldn't find an app to import %s fromN)splitranger+   r=   r	   )r   combinationsr"   entryr   )r7   r   r      s    


r   c              C   s2   t tdd} | dkrdS tjjd\}}t||S )z(
    Return the profile model class
    AUTH_PROFILE_MODULENr   )r4   r   rC   r?   	get_model)setting	app_label
model_namer   r   r   get_profile_class   s
    	rH   c             C   s   | dk	o| t jkS )z6
    Test if a certain Oscar feature is disabled.
    N)r   OSCAR_HIDDEN_FEATURES)Zfeature_namer   r   r   feature_hidden   s    rJ   c             C   s^   yt j| |S  tk
rX   t jrRt j rRt j| }td|jtf  t j	| |S  Y nX dS )a^  
    Fetches a Django model using the app registry.

    This doesn't require that an app with the given app label exists,
    which makes it safe to call when the registry is being populated.
    All other methods to access models might raise an exception about the
    registry not being ready yet.
    Raises LookupError if model isn't found.
    z%s.%sN)
r   rD   r   
apps_readymodels_readyget_app_configr   namer   get_registered_model)rF   rG   
app_configr   r   r   rD      s    

rD   c             C   s.   yt j| | W n tk
r$   dS X dS dS )z
    Checks whether a given model is registered. This is used to only
    register Oscar models if they aren't overridden by a forked app.
    FTN)r   rO   LookupError)rF   rG   r   r   r   is_model_registered  s
    rR   )r   )r   ) r'   r)   	importlibr   django.appsr   Zdjango.apps.configr   django.confr   django.core.exceptionsr   Zdjango.utils.lru_cacher   django.utils.module_loadingr   Zoscar.core.exceptionsr	   r
   r   r   r   r   r#   r   r!   r=   r   rH   rJ   rD   rR   r   r   r   r   <module>   s*   

T!