Esempio n. 1
0
def default_class_loader(module_label, classnames, module_prefix):
    """
    Dynamically import a list of classes from the given module.

    This works by looking up a matching app from the app registry,
    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
    """

    if '.' not in module_label:
        # Importing from top-level modules is not supported, e.g.
        # get_class('shipping', 'Scale'). That should be easy to fix,
        # but @maikhoepfel had a stab and could not get it working reliably.
        # Overridable classes in a __init__.py might not be a good idea anyway.
        raise ValueError(
            "Importing from top-level modules is not supported")

    # import from Oscar package (should succeed in most cases)
    # e.g. 'oscar.apps.dashboard.catalogue.forms'
    oscar_module_label = "%s.%s" % (module_prefix, module_label)
    oscar_module = _import_module(oscar_module_label, classnames)

    # returns e.g. 'oscar.apps.dashboard.catalogue',
    # 'yourproject.apps.dashboard.catalogue' or 'dashboard.catalogue',
    # depending on what is set in INSTALLED_APPS
    app_name = _find_registered_app_name(module_label)
    if app_name.startswith('%s.' % module_prefix):
        # The entry is obviously an Oscar one, we don't import again
        local_module = None
    else:
        # Attempt to import the classes from the local module
        # e.g. 'yourproject.dashboard.catalogue.forms'
        local_module_label = '.'.join(app_name.split('.') + module_label.split('.')[1:])
        local_module = _import_module(local_module_label, classnames)

    if oscar_module is local_module is None:
        # This intentionally doesn't raise an ImportError, because ImportError
        # can get masked in complex circular import scenarios.
        raise ModuleNotFoundError(
            "The module with label '%s' could not be imported. This either"
            "means that it indeed does not exist, or you might have a problem"
            " with a circular import." % module_label
        )

    # return imported classes, giving preference to ones from the local package
    return _pluck_classes([local_module, oscar_module], classnames)
Esempio n. 2
0
def get_classes(module_label, classnames):
    """
    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 Oscar app (assuming the matched module isn't in Oscar).

    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
    """

    # e.g. split 'dashboard.catalogue.forms' in 'dashboard.catalogue', 'forms'
    package, module = module_label.rsplit('.', 1)

    # import from Oscar package (should succeed in most cases)
    # e.g. 'oscar.apps.dashboard.catalogue.forms'
    oscar_module_label = "oscar.apps.%s" % module_label
    oscar_module = _import_oscar_module(oscar_module_label, classnames)

    # returns e.g. 'oscar.apps.dashboard.catalogue',
    # 'yourproject.apps.dashboard.catalogue' or 'dashboard.catalogue'
    installed_apps_entry = _get_installed_apps_entry(package)
    if not installed_apps_entry.startswith('oscar.apps.'):
        # Attempt to import the classes from the local module
        # e.g. 'yourproject.dashboard.catalogue.forms'
        local_module_label = installed_apps_entry + '.' + module
        local_module = _import_local_module(local_module_label, classnames)
    else:
        # The entry is obviously an Oscar one, we don't import again
        local_module = None

    if oscar_module is local_module is None:
        # This intentionally doesn't rise an ImportError, because it would get
        # masked by in some circular import scenarios.
        raise ModuleNotFoundError(
            "The module with label '%s' could not be imported. This either"
            "means that it indeed does not exist, or you might have a problem"
            " with a circular import." % module_label
        )

    # return imported classes, giving preference to ones from the local package
    return _pluck_classes([local_module, oscar_module], classnames)
Esempio n. 3
0
def default_class_loader(module_label, classnames, module_prefix):
    """
    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

    动态导入给定模块的类列表。
    这是通过循环``INSTALLED_APPS``并寻找与传递的模块标签的匹配来实现的。 如果在
    匹配模块中找不到请求的类,那么我们尝试从相应的核心应用程序导入它。
    这与用于动态加载模型的``django.db.models.get_model``函数非常相似。 这个函数
    更通用,因为它可以从匹配的应用程序加载任何类,而不仅仅是模型。
    Args:
        module_label(str):模块标签,包含应用标签和模块名称,用点分隔。 例如,'catalogue.forms'。
        classname(str):要导入的类的名称。
    Returns:
        请求的类对象,如果找不到,则为“无”

    例子:
        加载一个类:
        >>> get_class('dashboard.catalogue.forms', 'ProductForm')
        oscar.apps.dashboard.catalogue.forms.ProductForm
        加载类列表:
        >>> get_classes('dashboard.catalogue.forms',
        ...             ['ProductForm', 'StockRecordForm'])
        [oscar.apps.dashboard.catalogue.forms.ProductForm,
        oscar.apps.dashboard.catalogue.forms.StockRecordForm]

     Raises:
         AppNotFoundError:如果在``INSTALLED_APPS``中找不到与传递的模块标签匹配的应用程序。
         ImportError:如果尝试导入类引发了``ImportError``,则会重新引发它
    """

    if '.' not in module_label:
        # Importing from top-level modules is not supported, e.g.
        # get_class('shipping', 'Scale'). That should be easy to fix,
        # but @maikhoepfel had a stab and could not get it working reliably.
        # Overridable classes in a __init__.py might not be a good idea anyway.
        # 不支持从顶级模块导入,例如 get_class('shipping','Scale')。 这应该
        # 很容易修复,但@maikhoepfel有一个刺,无法让它可靠地工作。
        # 无论如何,__ init__.py中的可覆盖类可能不是一个好主意。
        raise ValueError(
            "Importing from top-level modules is not supported")

    # import from Oscar package (should succeed in most cases)
    # e.g. 'oscar.apps.dashboard.catalogue.forms'
    # 从奥斯卡包装进口(在大多数情况下应该成功),
    # 例如'oscar.apps.dashboard.catalogue.forms'
    oscar_module_label = "%s.%s" % (module_prefix, module_label)
    oscar_module = _import_module(oscar_module_label, classnames)

    # returns e.g. 'oscar.apps.dashboard.catalogue',
    # 'yourproject.apps.dashboard.catalogue' or 'dashboard.catalogue',
    # depending on what is set in INSTALLED_APPS

    # 返回 例如 'oscar.apps.dashboard.catalogue',
    # 'yourproject.apps.dashboard.catalogue'或'dashboard.catalogue',
    # 具体取决于INSTALLED_APPS中的设置
    installed_apps_entry, app_name = _find_installed_apps_entry(module_label)
    if installed_apps_entry.startswith('%s.' % module_prefix):
        # The entry is obviously an Oscar one, we don't import again
        # 条目显然是Oscar的,我们不会再次导入。
        local_module = None
    else:
        # Attempt to import the classes from the local module
        # e.g. 'yourproject.dashboard.catalogue.forms'
        # 尝试从本地模块导入类
        # 例如'yourproject.dashboard.catalogue.forms'
        sub_module = module_label.replace(app_name, '', 1)
        local_module_label = installed_apps_entry + sub_module
        local_module = _import_module(local_module_label, classnames)

    # Checking whether module label has corresponding move module in the MOVED_ITEMS dictionary.
    # If it does, checking if any of the loading classes moved to another module.
    # Finally, it they did, importing move module and showing deprecation warning as well.
    # 检查模块标签是否在MOVED_ITEMS字典中有相应的移动模块。
    # 如果是,请检查是否有任何加载类移动到另一个模块。
    # 最后,他们做了,导入移动模块并显示弃用警告。
    oscar_move_item = MOVED_ITEMS.get(oscar_module_label, None)
    if oscar_move_item:
        oscar_move_module_label = oscar_move_item[0]
        oscar_move_classnames = oscar_move_item[1]
        oscar_moved_classnames = list(set(oscar_move_classnames).intersection(classnames))
        if oscar_moved_classnames:
            warnings.warn(
                'Classes %s has recently moved to the new destination module - %s, '
                'please update your imports.' % (', '.join(oscar_moved_classnames),
                                                 oscar_move_module_label),
                DeprecationWarning, stacklevel=2)
            oscar_move_module = _import_module(oscar_move_module_label, classnames)
        else:
            oscar_move_module = None
    else:
        oscar_move_module = None

    if oscar_module is oscar_move_module is local_module is None:
        # This intentionally doesn't raise an ImportError, because ImportError
        # can get masked in complex circular import scenarios.
        # 这故意不会引发ImportError,因为在复杂的循环导入方案中可能会掩盖ImportError。
        raise ModuleNotFoundError(
            "The module with label '%s' could not be imported. This either"
            "means that it indeed does not exist, or you might have a problem"
            " with a circular import." % module_label
        )

    # return imported classes, giving preference to ones from the local package
    # 返回导入的类,优先使用本地包中的类
    return _pluck_classes([local_module, oscar_module, oscar_move_module], classnames)
Esempio n. 4
0
def default_class_loader(module_label, classnames, module_prefix):
    """
    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
    """

    if '.' not in module_label:
        # Importing from top-level modules is not supported, e.g.
        # get_class('shipping', 'Scale'). That should be easy to fix,
        # but @maikhoepfel had a stab and could not get it working reliably.
        # Overridable classes in a __init__.py might not be a good idea anyway.
        raise ValueError("Importing from top-level modules is not supported")

    # import from Oscar package (should succeed in most cases)
    # e.g. 'oscar.apps.dashboard.catalogue.forms'
    oscar_module_label = "%s.%s" % (module_prefix, module_label)
    oscar_module = _import_module(oscar_module_label, classnames)

    # returns e.g. 'oscar.apps.dashboard.catalogue',
    # 'yourproject.apps.dashboard.catalogue' or 'dashboard.catalogue',
    # depending on what is set in INSTALLED_APPS
    installed_apps_entry, app_name = _find_installed_apps_entry(module_label)
    if installed_apps_entry.startswith('%s.' % module_prefix):
        # The entry is obviously an Oscar one, we don't import again
        local_module = None
    else:
        # Attempt to import the classes from the local module
        # e.g. 'yourproject.dashboard.catalogue.forms'
        sub_module = module_label.replace(app_name, '', 1)
        local_module_label = installed_apps_entry + sub_module
        local_module = _import_module(local_module_label, classnames)

    # Checking whether module label has corresponding move module in the MOVED_ITEMS dictionary.
    # If it does, checking if any of the loading classes moved to another module.
    # Finally, it they did, importing move module and showing deprecation warning as well.
    oscar_move_item = MOVED_ITEMS.get(oscar_module_label, None)
    if oscar_move_item:
        oscar_move_module_label = oscar_move_item[0]
        oscar_move_classnames = oscar_move_item[1]
        oscar_moved_classnames = list(
            set(oscar_move_classnames).intersection(classnames))
        if oscar_moved_classnames:
            warnings.warn(
                'Classes %s has recently moved to the new destination module - %s, '
                'please update your imports.' %
                (', '.join(oscar_moved_classnames), oscar_move_module_label),
                DeprecationWarning,
                stacklevel=2)
            oscar_move_module = _import_module(oscar_move_module_label,
                                               classnames)
        else:
            oscar_move_module = None
    else:
        oscar_move_module = None

    if oscar_module is oscar_move_module is local_module is None:
        # This intentionally doesn't raise an ImportError, because ImportError
        # can get masked in complex circular import scenarios.
        raise ModuleNotFoundError(
            "The module with label '%s' could not be imported. This either"
            "means that it indeed does not exist, or you might have a problem"
            " with a circular import." % module_label)

    # return imported classes, giving preference to ones from the local package
    return _pluck_classes([local_module, oscar_module, oscar_move_module],
                          classnames)
Esempio n. 5
0
def get_api_classes(module_label, classnames):
    """
    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 main
    oscarapi 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('oscarapi.serializers.basket', 'BasketSerializer')
        oscarapi.serializers.basket.BasketSerializer

        Load a list of classes:

        >>> get_classes('oscarapi.serializers.basket',
        ...             ['BasketSerializer', 'BasketLineSerializer'])
        [oscarapi.serializers.basket.BasketSerializer,
         oscarapi.serializers.basket.BasketLineSerializer]

    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
    """
    if '.' not in module_label:
        raise ValueError("Importing from top-level modules is not supported")

    # import from Oscar package (should succeed in most cases)
    # e.g. 'oscarapi.serializers.basket.BasketSerializer'
    oscarapi_module_label = module_label
    oscarapi_module = _import_module(oscarapi_module_label, classnames)

    installed_apps_entry, app_name = _find_installed_apps_entry(module_label)
    if installed_apps_entry.startswith('oscarapi.'):
        # The entry is obviously an Oscar Api one, we don't import again
        local_module = None
    else:
        # Attempt to import the classes from the local module
        # e.g. 'yourproject.oscarapi.models.ApiKey'
        sub_module = module_label.replace(app_name, '', 1)
        local_module_label = installed_apps_entry + sub_module
        local_module = _import_module(local_module_label, classnames)

    if oscarapi_module is local_module is None:
        # This intentionally doesn't raise an ImportError, because ImportError
        # can get masked in complex circular import scenarios.
        raise ModuleNotFoundError(
            "The module with label '%s' could not be imported. This either"
            "means that it indeed does not exist, or you might have a problem"
            " with a circular import." % module_label)

    # return imported classes, giving preference to ones from the local package
    return _pluck_classes([local_module, oscarapi_module], classnames)