winordie
@winordie
Лучшая документация -- исходники

Несовместимость Pycharm 4 и django-oscar?

Проблема специфическая и касается только связки Pycharm 4 и проекта django-oscar
У django-oscar есль функция get_classes():
def get_classes(module_label, classnames):
    ...
    oscar_module_label = "oscar.apps.%s" % module_label
    oscar_module = _import_module(oscar_module_label, classnames)

    installed_apps_entry, app_name = _find_installed_apps_entry(module_label)
    if installed_apps_entry.startswith('oscar.apps.'):
        # 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, '')
        local_module_label = installed_apps_entry + sub_module
        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)

def _import_module(module_label, classnames):
    try:
        return __import__(module_label, fromlist=classnames)
    except ImportError:
        __, __, exc_traceback = sys.exc_info()
        frames = traceback.extract_tb(exc_traceback)
        if len(frames) > 1:
            raise

Назначение функции -- импортировать классы из модуля
my_class_1, my_class_2 = get_classes('myapp.mymodule', ['MyClass1', 'MyClass2'])
аналогичко
from path_to_myapp.myapp.mymodule import MyClass1 as my_class_1
from path_to_myapp.myapp.mymodule import MyClass2 as my_class_2

Логика функции проста:
Сначала ищем модуль среди приложений oscar'а
Если в приложениях oscar'а не найдено (или переопределено в пользовательских), то ещем среди пользовательских приложений
Если и там нет выкидываем исключение.

При запуске в режиме дебаггинга вываливается ошибка, что модуля не существует.
Причина ошибки в последних четырех строках функции _import_module()
__, __, exc_traceback = sys.exc_info()
frames = traceback.extract_tb(exc_traceback)
if len(frames) > 1:
    raise

При ошибке frames равен:
frames = [
('/home/dfdf/.virtualenvs/myenv/local/lib/python2.7/site-packages/oscar/core/loading.py', 159, '_import_module', 'return __import__(module_label, fromlist=classnames)'), 
('/opt/pycharm-4.0/helpers/pydev/_pydev_imps/_pydev_pluginbase.py', 449, 'plugin_import', 'fromlist, level)')]

Т.е. логика программы ждет одно исключение импорта (и это нормально), но деббагер добавляет еще свое исключение
Таким образом проблема решается простым исправлением if len(frames) > 1: на if len(frames) > 2:
Но так как все вышеприведенное я написал не для того чтобы показать какой я умный, то вопрос:
Это ошибка в дебаггере?
Или все же проблема в логике программы?
Ну или никто не виноват, и это просто недопонимание между разработчиками двух проектов (pycharm и django-oscar)?

Ведь по идее не "комильфо" править исходники проекта. И не вылезет ли это боком позже?
  • Вопрос задан
  • 2757 просмотров
Решения вопроса 1
crazyzubr
@crazyzubr
Python backend-developer
Раз исходники открыты можно сделать форк и добавить изменение туда. К тому же можно сделать пулл-реквест с описанием данной проблемы. Полагаю разработчики приложения смогут лучше прокомментировать это.

Также можно написать и в поддержку Pycharm, но нужно иметь в виду, что ответ будет не скоро )
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы