コード例 #1
0
def infer_key_classes(node, context=None):
    for arg in node.args:
        # typically the class of the foreign key will
        # be the first argument, so we'll go from left to right
        if isinstance(arg, (nodes.Name, nodes.Getattr)):
            try:
                key_cls = None
                for inferred in arg.infer(context=context):
                    key_cls = inferred
                    break
            except InferenceError:
                continue
            else:
                if key_cls is not None:
                    break
        elif isinstance(arg, nodes.Const):
            try:
                model_name = arg.value.split('.')[-1]  # can be 'Model' or 'app.Model'
            except AttributeError:
                break

            for module in MANAGER.astroid_cache.values():
                if model_name in module.locals:
                    class_defs = [
                        module_node for module_node in module.lookup(model_name)[1]
                        if isinstance(module_node, nodes.ClassDef)
                        and node_is_subclass(module_node, 'django.db.models.base.Model')
                    ]
                    if class_defs:
                        return iter([instantiate_class(class_defs[0])()])
    else:
        raise UseInferenceDefault
    return iter([instantiate_class(key_cls)()])
コード例 #2
0
def foreign_key_sets(chain, node):
    """
    When a Django model has a ForeignKey to another model, the target
    of the foreign key gets a '<modelname>_set' attribute for accessing
    a queryset of the model owning the foreign key - eg:

    class ModelA(models.Model):
        pass

    class ModelB(models.Model):
        a = models.ForeignKey(ModelA)

    Now, ModelA instances will have a modelb_set attribute.
    """
    if node.attrname.endswith('_set'):
        children = list(node.get_children())
        for child in children:
            try:
                inferred = child.infered()
            except InferenceError:
                pass
            else:
                for cls in inferred:
                    if node_is_subclass(cls, 'django.db.models.base.Model'):
                        # This means that we are looking at a subclass of models.Model
                        # and something is trying to access a <something>_set attribute.
                        # Since this could exist, we will return so as not to raise an
                        # error.
                        return
    chain()
コード例 #3
0
ファイル: __init__.py プロジェクト: mbarrien/pylint-django
def foreign_key_sets(chain, node):
    """
    When a Django model has a ForeignKey to another model, the target
    of the foreign key gets a '<modelname>_set' attribute for accessing
    a queryset of the model owning the foreign key - eg:

    class ModelA(models.Model):
        pass

    class ModelB(models.Model):
        a = models.ForeignKey(ModelA)

    Now, ModelA instances will have a modelb_set attribute.
    """
    if node.attrname.endswith('_set'):
        children = list(node.get_children())
        for child in children:
            try:
                inferred = child.infered()
            except InferenceError:
                pass
            else:
                for cls in inferred:
                    if node_is_subclass(cls, 'django.db.models.base.Model'):
                        # This means that we are looking at a subclass of models.Model
                        # and something is trying to access a <something>_set attribute.
                        # Since this could exist, we will return so as not to raise an
                        # error.
                        return
    chain()
コード例 #4
0
def is_model_test_case_subclass(node):
    """Checks that node is derivative of TestCase class."""
    if not node.name.endswith('Test') and not isinstance(
            node.parent, ClassDef):
        return False

    return node_is_subclass(node, 'django.test.testcases.TestCase')
コード例 #5
0
ファイル: models.py プロジェクト: jproffitt/pylint-django
    def visit_class(self, node):
        if not node_is_subclass(node, 'django.db.models.base.Model'):
            # we only care about models
            return

        for child in node.get_children():
            if isinstance(child, Assign):
                grandchildren = list(child.get_children())
  
                if not isinstance(grandchildren[0], AssName):
                    continue

                name = grandchildren[0].name
                if name != '__unicode__':
                    continue

                assigned = grandchildren[1].infered()[0]
                if assigned.callable():
                    return

                self.add_message('E%s01' % BASE_ID, args=node.name, node=node)
                return

            if isinstance(child, Function) and child.name == '__unicode__':
                if sys.version_info[0] >= 3:
                    self.add_message('W%s02' % BASE_ID, args=node.name, node=node)
                return

        # if we get here, then we have no __unicode__ method
        if sys.version_info[0] >= 3:
            return

        self.add_message('W%s01' % BASE_ID, args=node.name, node=node)
コード例 #6
0
def is_model_factory_meta_subclass(node):
    """Checks that node is derivative of DjangoModelFactory class."""
    if node.name != 'Meta' or not isinstance(node.parent, ClassDef):
        return False

    parents = ('factory.django.DjangoModelFactory',
               '.DjangoModelFactory',)
    return node_is_subclass(node.parent, *parents)
コード例 #7
0
def is_model_mpttmeta_subclass(node):
    """Checks that node is derivative of MPTTMeta class."""
    if node.name != 'MPTTMeta' or not isinstance(node.parent, Class):
        return False

    parents = ('django.db.models.base.Model', 'django.forms.forms.Form',
               'django.forms.models.ModelForm')
    return any([node_is_subclass(node.parent, parent) for parent in parents])
コード例 #8
0
ファイル: __init__.py プロジェクト: jproffitt/pylint-django
def is_model_meta_subclass(node):
    if node.name != 'Meta' or not isinstance(node.parent, Class):
        return False

    parents = ('django.db.models.base.Model',
               'django.forms.forms.Form',
               'django.forms.models.ModelForm')
    return any([node_is_subclass(node.parent, parent) for parent in parents])
コード例 #9
0
def is_model_media_subclass(node):
    """Checks that node is derivative of Media class."""
    if node.name != 'Media' or not isinstance(node.parent, Class):
        return False

    parents = ('django.contrib.admin.options.ModelAdmin',
               'django.forms.widgets.Media', 'django.db.models.base.Model',
               'django.forms.forms.Form', 'django.forms.models.ModelForm')
    return any([node_is_subclass(node.parent, parent) for parent in parents])
コード例 #10
0
ファイル: __init__.py プロジェクト: mbarrien/pylint-django
def is_model_meta_subclass(node):
    """Checks that node is derivative of Meta class."""
    if node.name != 'Meta' or not isinstance(node.parent, Class):
        return False

    parents = ('django.db.models.base.Model',
               'django.forms.forms.Form',
               'django.forms.models.ModelForm')
    return any([node_is_subclass(node.parent, parent) for parent in parents])
コード例 #11
0
    def _visit_classdef(self, node):
        """Class visitor."""
        if not node_is_subclass(node, 'django.db.models.base.Model', '.Model'):
            # we only care about models
            return

        for child in node.get_children():
            if _is_meta_with_abstract(child):
                return

            if isinstance(child, Assign):
                grandchildren = list(child.get_children())

                if not isinstance(grandchildren[0], AssignName):
                    continue

                name = grandchildren[0].name
                if name != '__unicode__':
                    continue

                grandchild = grandchildren[1]
                assigned = inferred(grandchild)()[0]

                if assigned.callable():
                    return

                self.add_message('E%s01' % BASE_ID, args=node.name, node=node)
                return

            if isinstance(child, FunctionDef) and child.name == '__unicode__':
                if PY3:
                    self.add_message('W%s02' % BASE_ID,
                                     args=node.name,
                                     node=node)
                return

        # if we get here, then we have no __unicode__ method directly on the class itself
        if PY3:
            return

        # a different warning is emitted if a parent declares __unicode__
        for method in node.methods():
            if method.name == '__unicode__':
                # this happens if a parent declares the unicode method but
                # this node does not
                self.add_message('W%s03' % BASE_ID, args=node.name, node=node)
                return

        # if the Django compatibility decorator is used then we don't emit a warning
        # see https://github.com/landscapeio/pylint-django/issues/10
        if node.decorators is not None:
            for decorator in node.decorators.nodes:
                if getattr(decorator, 'name',
                           None) == 'python_2_unicode_compatible':
                    return

        self.add_message('W%s01' % BASE_ID, args=node.name, node=node)
コード例 #12
0
def infer_key_classes(node, context=None):
    keyword_args = [kw.value for kw in node.keywords]
    all_args = chain(node.args, keyword_args)

    for arg in all_args:
        # typically the class of the foreign key will
        # be the first argument, so we'll go from left to right
        if isinstance(arg, (nodes.Name, nodes.Attribute)):
            try:
                key_cls = None
                for inferred in arg.infer(context=context):
                    key_cls = inferred
                    break
            except InferenceError:
                continue
            else:
                if key_cls is not None:
                    break
        elif isinstance(arg, nodes.Const):
            try:
                # can be 'Model' or 'app.Model'
                module_name, _, model_name = arg.value.rpartition('.')
            except AttributeError:
                break

            # when ForeignKey is specified only by class name we assume that
            # this class must be found in the current module
            if not module_name:
                current_module = node.frame()
                while not isinstance(current_module, nodes.Module):
                    current_module = current_module.parent.frame()

                module_name = current_module.name
            elif not module_name.endswith('models'):
                # otherwise Django allows specifying an app name first, e.g.
                # ForeignKey('auth.User') so we try to convert that to
                # 'auth.models', 'User' which works nicely with the `endswith()`
                # comparison below
                module_name += '.models'

            for module in MANAGER.astroid_cache.values():
                # only load model classes from modules which match the module in
                # which *we think* they are defined. This will prevent infering
                # other models of the same name which are found elsewhere!
                if model_name in module.locals and module.name.endswith(module_name):
                    class_defs = [
                        module_node for module_node in module.lookup(model_name)[1]
                        if isinstance(module_node, nodes.ClassDef)
                        and node_is_subclass(module_node, 'django.db.models.base.Model')
                    ]
                    if class_defs:
                        return iter([class_defs[0].instantiate_class()])
    else:
        raise UseInferenceDefault
    return iter([key_cls.instantiate_class()])
コード例 #13
0
def is_model_view_subclass_method_shouldnt_be_function(node):
    """Checks that node is get or post method of the View class."""
    if node.name not in ('get', 'post'):
        return False

    parent = node.parent
    while parent and not isinstance(parent, ScopedClass):
        parent = parent.parent

    subclass = '.View'
    return parent is not None and parent.name.endswith('View') and node_is_subclass(parent, subclass)
コード例 #14
0
def foreign_key_sets(chain, node):
    """
    When a Django model has a ForeignKey to another model, the target
    of the foreign key gets a '<modelname>_set' attribute for accessing
    a queryset of the model owning the foreign key - eg:

    class ModelA(models.Model):
        pass

    class ModelB(models.Model):
        a = models.ForeignKey(ModelA)

    Now, ModelA instances will have a modelb_set attribute.

    It's also possible to explicitly name the relationship using the related_name argument
    to the ForeignKey constructor. As it's impossible to know this without inspecting all
    models before processing, we'll instead do a "best guess" approach and see if the attribute
    being accessed goes on to be used as a queryset. This is via 'duck typing': if the method
    called on the attribute being accessed is something we might find in a queryset, we'll
    warn.
    """
    quack = False

    if node.attrname in MANAGER_ATTRS or node.attrname.endswith('_set'):
        # if this is a X_set method, that's a pretty strong signal that this is the default
        # Django name, rather than one set by related_name
        quack = True
    else:
        # we will
        if isinstance(node.parent, Attribute):
            func_name = getattr(node.parent, 'attrname', None)
            if func_name in MANAGER_ATTRS:
                quack = True

    if quack:
        children = list(node.get_children())
        for child in children:
            try:
                inferred_cls = child.inferred()
            except InferenceError:
                pass
            else:
                for cls in inferred_cls:
                    if (node_is_subclass(cls,
                                         'django.db.models.manager.Manager',
                                         'django.db.models.base.Model',
                                         '.Model',
                                         'django.db.models.fields.related.ForeignObject')):
                        # This means that we are looking at a subclass of models.Model
                        # and something is trying to access a <something>_set attribute.
                        # Since this could exist, we will return so as not to raise an
                        # error.
                        return
    chain()
コード例 #15
0
def is_model_view_subclass_method_shouldnt_be_function(node):
    """Checks that node is get or post method of the View class."""
    if node.name not in ('get', 'post'):
        return False

    parent = node.parent
    while parent and not isinstance(parent, ScopedClass):
        parent = parent.parent

    subclass = '.View'
    return parent is not None and parent.name.endswith('View') and node_is_subclass(parent, subclass)
コード例 #16
0
ファイル: __init__.py プロジェクト: mbarrien/pylint-django
def is_model_media_subclass(node):
    """Checks that node is derivative of Media class."""
    if node.name != 'Media' or not isinstance(node.parent, Class):
        return False

    parents = ('django.contrib.admin.options.ModelAdmin',
               'django.forms.widgets.Media',
               'django.db.models.base.Model',
               'django.forms.forms.Form',
               'django.forms.models.ModelForm')
    return any([node_is_subclass(node.parent, parent) for parent in parents])
コード例 #17
0
ファイル: models.py プロジェクト: Coldwings/pylint-django
    def _visit_classdef(self, node):
        """Class visitor."""
        if not node_is_subclass(node, 'django.db.models.base.Model', '.Model'):
            # we only care about models
            return

        for child in node.get_children():
            if _is_meta_with_abstract(child):
                return

            if isinstance(child, Assign):
                grandchildren = list(child.get_children())

                if not isinstance(grandchildren[0], AssignName):
                    continue

                name = grandchildren[0].name
                if name != '__unicode__':
                    continue

                grandchild = grandchildren[1]
                assigned = inferred(grandchild)()[0]

                if assigned.callable():
                    return

                self.add_message('E%s01' % BASE_ID, args=node.name, node=node)
                return

            if isinstance(child, FunctionDef) and child.name == '__unicode__':
                if PY3:
                    self.add_message('W%s02' % BASE_ID, args=node.name, node=node)
                return

        # if we get here, then we have no __unicode__ method directly on the class itself
        if PY3:
            return

        # a different warning is emitted if a parent declares __unicode__
        for method in node.methods():
            if method.name == '__unicode__':
                # this happens if a parent declares the unicode method but
                # this node does not
                self.add_message('W%s03' % BASE_ID, args=node.name, node=node)
                return

        # if the Django compatibility decorator is used then we don't emit a warning
        # see https://github.com/landscapeio/pylint-django/issues/10
        if node.decorators is not None:
            for decorator in node.decorators.nodes:
                if getattr(decorator, 'name', None) == 'python_2_unicode_compatible':
                    return

        self.add_message('W%s01' % BASE_ID, args=node.name, node=node)
コード例 #18
0
def foreign_key_sets(chain, node):
    """
    When a Django model has a ForeignKey to another model, the target
    of the foreign key gets a '<modelname>_set' attribute for accessing
    a queryset of the model owning the foreign key - eg:

    class ModelA(models.Model):
        pass

    class ModelB(models.Model):
        a = models.ForeignKey(ModelA)

    Now, ModelA instances will have a modelb_set attribute.

    It's also possible to explicitly name the relationship using the related_name argument
    to the ForeignKey constructor. As it's impossible to know this without inspecting all
    models before processing, we'll instead do a "best guess" approach and see if the attribute
    being accessed goes on to be used as a queryset. This is via 'duck typing': if the method
    called on the attribute being accessed is something we might find in a queryset, we'll
    warn.
    """
    quack = False

    if node.attrname in MANAGER_ATTRS or node.attrname.endswith('_set'):
        # if this is a X_set method, that's a pretty strong signal that this is the default
        # Django name, rather than one set by related_name
        quack = True
    else:
        # we will
        if isinstance(node.parent, Attribute):
            func_name = getattr(node.parent, 'attrname', None)
            if func_name in MANAGER_ATTRS:
                quack = True

    if quack:
        children = list(node.get_children())
        for child in children:
            try:
                inferred_cls = inferred(child)()
            except InferenceError:
                pass
            else:
                for cls in inferred_cls:
                    if (node_is_subclass(cls,
                                         'django.db.models.manager.Manager',
                                         'django.db.models.base.Model',
                                         '.Model')):
                        # This means that we are looking at a subclass of models.Model
                        # and something is trying to access a <something>_set attribute.
                        # Since this could exist, we will return so as not to raise an
                        # error.
                        return
    chain()
コード例 #19
0
def _get_model_class_defs_from_module(module, model_name, module_name):
    class_defs = []
    for module_node in module.lookup(model_name)[1]:
        if (isinstance(module_node, nodes.ClassDef) and node_is_subclass(
                module_node, 'django.db.models.base.Model')):
            class_defs.append(module_node)
        elif isinstance(module_node, nodes.ImportFrom):
            imported_module = module_node.do_import_module()
            class_defs.extend(
                _get_model_class_defs_from_module(imported_module, model_name,
                                                  module_name))
    return class_defs
コード例 #20
0
def is_model_mpttmeta_subclass(node):
    """Checks that node is derivative of MPTTMeta class."""
    if node.name != 'MPTTMeta' or not isinstance(node.parent, ClassDef):
        return False

    parents = ('django.db.models.base.Model',
               '.Model',  # for the transformed version used in this plugin
               'django.forms.forms.Form',
               '.Form',
               'django.forms.models.ModelForm',
               '.ModelForm')
    return node_is_subclass(node.parent, *parents)
コード例 #21
0
def is_model_mpttmeta_subclass(node):
    """Checks that node is derivative of MPTTMeta class."""
    if node.name != 'MPTTMeta' or not isinstance(node.parent, ClassDef):
        return False

    parents = ('django.db.models.base.Model',
               '.Model',  # for the transformed version used in this plugin
               'django.forms.forms.Form',
               '.Form',
               'django.forms.models.ModelForm',
               '.ModelForm')
    return node_is_subclass(node.parent, *parents)
コード例 #22
0
ファイル: __init__.py プロジェクト: jproffitt/pylint-django
def is_model_field_display_method(node):
    if not node.attrname.endswith('_display'):
        return
    if not node.attrname.startswith('get_'):
        return

    if node.last_child():
        # TODO: could validate the names of the fields on the model rather than
        # blindly accepting get_*_display
        for cls in node.last_child().infered():
            if node_is_subclass(cls, 'django.db.models.base.Model'):
                return True
    return False
コード例 #23
0
def is_model_media_subclass(node):
    """Checks that node is derivative of Media class."""
    if node.name != 'Media' or not isinstance(node.parent, ClassDef):
        return False

    parents = ('django.contrib.admin.options.ModelAdmin',
               'django.forms.widgets.Media',
               'django.db.models.base.Model',
               '.Model',  # for the transformed version used in this plugin
               'django.forms.forms.Form',
               '.Form',
               'django.forms.models.ModelForm',
               '.ModelForm')
    return node_is_subclass(node.parent, *parents)
コード例 #24
0
def is_model_meta_subclass(node):
    """Checks that node is derivative of Meta class."""
    if node.name != 'Meta' or not isinstance(node.parent, Class):
        return False

    parents = ('django.db.models.base.Model',
               'django.forms.forms.Form',
               'django.forms.models.ModelForm',
               'rest_framework.serializers.ModelSerializer',
               'rest_framework.generics.GenericAPIView',
               'rest_framework.viewsets.ReadOnlyModelViewSet',
               'rest_framework.viewsets.ModelViewSet',
               'django_filters.filterset.FilterSet',)
    return any([node_is_subclass(node.parent, parent) for parent in parents])
コード例 #25
0
def is_model_field_display_method(node):
    """Accept model's fields with get_*_display names."""
    if not node.attrname.endswith('_display'):
        return
    if not node.attrname.startswith('get_'):
        return

    if node.last_child():
        # TODO: could validate the names of the fields on the model rather than
        # blindly accepting get_*_display
        for cls in node.last_child().infered():
            if node_is_subclass(cls, 'django.db.models.base.Model'):
                return True
    return False
コード例 #26
0
ファイル: __init__.py プロジェクト: Rahullaniya/rtre_project
def is_model_view_subclass_method_shouldnt_be_function(node):
    """Checks that node is a default http method (i.e get, post, put, and more) of the View class."""
    if node.name not in View.http_method_names:
        return False

    parent = node.parent
    while parent and not isinstance(parent, ScopedClass):
        parent = parent.parent

    subclass = ('django.views.View',
                'django.views.generic.View',
                'django.views.generic.base.View',)

    return parent is not None and node_is_subclass(parent, *subclass)
コード例 #27
0
def is_model_view_subclass_method_shouldnt_be_function(node):
    """Checks that node is get or post method of the View class."""
    if node.name not in ('get', 'post'):
        return False

    parent = node.parent
    while parent and not isinstance(parent, ScopedClass):
        parent = parent.parent

    subclass = ('django.views.View',
                'django.views.generic.View',
                'django.views.generic.base.View',)

    return parent is not None and node_is_subclass(parent, *subclass)
コード例 #28
0
def _attribute_is_magic(node, attrs, parents):
    """Checks that node is an attribute used inside one of allowed parents"""
    if node.attrname not in attrs:
        return False
    if not node.last_child():
        return False

    try:
        for cls in inferred(node.last_child())():
            if isinstance(cls, Super):
                cls = cls._self_class
            if node_is_subclass(cls, *parents) or cls.qname() in parents:
                return True
    except InferenceError:
        pass
    return False
コード例 #29
0
def _attribute_is_magic(node, attrs, parents):
    """Checks that node is an attribute used inside one of allowed parents"""
    if node.attrname not in attrs:
        return False
    if not node.last_child():
        return False

    try:
        for cls in node.last_child().inferred():
            if isinstance(cls, Super):
                cls = cls._self_class  # pylint: disable=protected-access
            if node_is_subclass(cls, *parents) or cls.qname() in parents:
                return True
    except InferenceError:
        pass
    return False
コード例 #30
0
def is_model_meta_subclass(node):
    """Checks that node is derivative of Meta class."""
    if node.name != 'Meta' or not isinstance(node.parent, Class):
        return False

    parents = (
        'django.db.models.base.Model',
        'django.forms.forms.Form',
        'django.forms.models.ModelForm',
        'rest_framework.serializers.ModelSerializer',
        'rest_framework.generics.GenericAPIView',
        'rest_framework.viewsets.ReadOnlyModelViewSet',
        'rest_framework.viewsets.ModelViewSet',
        'django_filters.filterset.FilterSet',
    )
    return any([node_is_subclass(node.parent, parent) for parent in parents])
コード例 #31
0
def is_model_field_display_method(node):
    """Accept model's fields with get_*_display names."""
    if not node.attrname.endswith('_display'):
        return
    if not node.attrname.startswith('get_'):
        return

    if node.last_child():
        # TODO: could validate the names of the fields on the model rather than
        # blindly accepting get_*_display
        try:
            for cls in inferred(node.last_child())():
                if node_is_subclass(cls, 'django.db.models.base.Model', '.Model'):
                    return True
        except InferenceError:
            return False
    return False
コード例 #32
0
def is_model_meta_subclass(node):
    """Checks that node is derivative of Meta class."""
    if node.name != 'Meta' or not isinstance(node.parent, ClassDef):
        return False

    parents = ('.Model',  # for the transformed version used here
               'django.db.models.base.Model',
               '.Form',
               'django.forms.forms.Form',
               '.ModelForm',
               'django.forms.models.ModelForm',
               'rest_framework.serializers.ModelSerializer',
               'rest_framework.generics.GenericAPIView',
               'rest_framework.viewsets.ReadOnlyModelViewSet',
               'rest_framework.viewsets.ModelViewSet',
               'django_filters.filterset.FilterSet',)
    return node_is_subclass(node.parent, *parents)
コード例 #33
0
def is_model_meta_subclass(node):
    """Checks that node is derivative of Meta class."""
    if node.name != 'Meta' or not isinstance(node.parent, ClassDef):
        return False

    parents = ('.Model',  # for the transformed version used here
               'django.db.models.base.Model',
               '.Form',
               'django.forms.forms.Form',
               '.ModelForm',
               'django.forms.models.ModelForm',
               'rest_framework.serializers.BaseSerializer',
               'rest_framework.generics.GenericAPIView',
               'rest_framework.viewsets.ReadOnlyModelViewSet',
               'rest_framework.viewsets.ModelViewSet',
               'django_filters.filterset.FilterSet',)
    return node_is_subclass(node.parent, *parents)
コード例 #34
0
    def visit_classdef(self, node):
        """Class visitor."""
        if not node_is_subclass(node, 'django.forms.models.ModelForm',
                                '.ModelForm'):
            # we only care about forms
            return

        meta = _get_child_meta(node)

        if not meta:
            return

        for child in meta.get_children():
            if not isinstance(child, Assign):
                continue

            if child.targets[0].name == 'exclude':
                self.add_message('W%s04' % BASE_ID, node=child)
                break
コード例 #35
0
def is_model_factory(node):
    """Checks that node is derivative of DjangoModelFactory or SubFactory class."""
    try:
        parent_classes = node.expr.inferred()
    except:  # noqa: E722, pylint: disable=bare-except
        return False

    parents = ('factory.declarations.SubFactory', 'factory.django.DjangoModelFactory')

    for parent_class in parent_classes:
        try:
            if parent_class.qname() in parents:
                return True

            if node_is_subclass(parent_class, *parents):
                return True
        except AttributeError:
            continue

    return False
コード例 #36
0
ファイル: models.py プロジェクト: mbarrien/pylint-django
    def visit_class(self, node):
        """Class visitor."""
        if not node_is_subclass(node, 'django.db.models.base.Model'):
            # we only care about models
            return

        for child in node.get_children():
            if isinstance(child, Assign):
                grandchildren = list(child.get_children())

                if not isinstance(grandchildren[0], AssName):
                    continue

                name = grandchildren[0].name
                if name != '__unicode__':
                    continue

                assigned = grandchildren[1].infered()[0]
                if assigned.callable():
                    return

                self.add_message('E%s01' % BASE_ID, args=node.name, node=node)
                return

            if isinstance(child, Function) and child.name == '__unicode__':
                if sys.version_info[0] >= 3:
                    self.add_message('W%s02' % BASE_ID,
                                     args=node.name,
                                     node=node)
                return

        # if we get here, then we have no __unicode__ method
        if sys.version_info[0] >= 3:
            return

        self.add_message('W%s01' % BASE_ID, args=node.name, node=node)
コード例 #37
0
def foreign_key_sets(chain, node):
    """
    When a Django model has a ForeignKey to another model, the target
    of the foreign key gets a '<modelname>_set' attribute for accessing
    a queryset of the model owning the foreign key - eg:

    class ModelA(models.Model):
        pass

    class ModelB(models.Model):
        a = models.ForeignKey(ModelA)

    Now, ModelA instances will have a modelb_set attribute.

    It's also possible to explicitly name the relationship using the related_name argument
    to the ForeignKey constructor. As it's impossible to know this without inspecting all
    models before processing, we'll instead do a "best guess" approach and see if the attribute
    being accessed goes on to be used as a queryset. This is via 'duck typing': if the method
    called on the attribute being accessed is something we might find in a queryset, we'll
    warn.
    """
    quack = False

    if node.attrname.endswith('_set'):
        # if this is a X_set method, that's a pretty strong signal that this is the default
        # Django name, rather than one set by related_name
        quack = True
    else:
        # we will
        if isinstance(node.parent, Getattr):
            func_name = getattr(node.parent, 'attrname', None)

            # Note: it would have been nice to import the Manager object from Django and
            # get its attributes that way - and this used to be the method - but unfortunately
            # there's no guarantee that Django is properly configured at that stage, and importing
            # anything from the django.db package causes an ImproperlyConfigured exception.
            # Therefore we'll fall back on a hard-coded list of attributes which won't be as accurate,
            # but this is not 100% accurate anyway.
            manager_attrs = (
                'none',
                'all',
                'count',
                'dates',
                'distinct',
                'extra',
                'get',
                'get_or_create',
                'create',
                'bulk_create',
                'filter',
                'aggregate',
                'annotate',
                'complex_filter',
                'exclude',
                'in_bulk',
                'iterator',
                'latest',
                'order_by',
                'select_for_update',
                'select_related',
                'prefetch_related',
                'values',
                'values_list',
                'update',
                'reverse',
                'defer',
                'only',
                'using',
                'exists',
            )

            if func_name in manager_attrs:
                quack = True

    if quack:
        children = list(node.get_children())
        for child in children:
            try:
                inferred = child.infered()
            except InferenceError:
                pass
            else:
                for cls in inferred:
                    if node_is_subclass(cls, 'django.db.models.base.Model'):
                        # This means that we are looking at a subclass of models.Model
                        # and something is trying to access a <something>_set attribute.
                        # Since this could exist, we will return so as not to raise an
                        # error.
                        return
    chain()
コード例 #38
0
def is_class(class_name):
    """Shortcut for node_is_subclass."""
    return lambda node: node_is_subclass(node, class_name)
コード例 #39
0
ファイル: __init__.py プロジェクト: jproffitt/pylint-django
def is_class(class_name):
    return lambda node: node_is_subclass(node, class_name)
コード例 #40
0
 def visit_classdef(self, node):
     if node_is_subclass(
             node, "django.forms.forms.BaseForm",
             ".BaseForm") and not node_is_subclass(
                 node, "django.forms.models.ModelForm", ".ModelForm"):
         self.add_message("must-inherit-from-model-form", node=node)
コード例 #41
0
def is_model_admin_subclass(node):
    """Checks that node is derivative of ModelAdmin class."""
    if node.name[-5:] != 'Admin' or isinstance(node.parent, ClassDef):
        return False

    return node_is_subclass(node, 'django.contrib.admin.options.ModelAdmin')
コード例 #42
0
def is_class(class_name):
    """Shortcut for node_is_subclass."""
    return lambda node: node_is_subclass(node, class_name)
コード例 #43
0
 def visit_classdef(self, node):
     if node_is_subclass(
             node, 'django.forms.forms.BaseForm',
             '.BaseForm') and not node_is_subclass(
                 node, 'django.forms.models.ModelForm', '.ModelForm'):
         self.add_message('must-inherit-from-model-form', node=node)
コード例 #44
0
def is_model_test_case_subclass(node):
    """Checks that node is derivative of TestCase class."""
    if not node.name.endswith('Test') and not isinstance(node.parent, ClassDef):
        return False

    return node_is_subclass(node, 'django.test.testcases.TestCase')
コード例 #45
0
def foreign_key_sets(chain, node):
    """
    When a Django model has a ForeignKey to another model, the target
    of the foreign key gets a '<modelname>_set' attribute for accessing
    a queryset of the model owning the foreign key - eg:

    class ModelA(models.Model):
        pass

    class ModelB(models.Model):
        a = models.ForeignKey(ModelA)

    Now, ModelA instances will have a modelb_set attribute.

    It's also possible to explicitly name the relationship using the related_name argument
    to the ForeignKey constructor. As it's impossible to know this without inspecting all
    models before processing, we'll instead do a "best guess" approach and see if the attribute
    being accessed goes on to be used as a queryset. This is via 'duck typing': if the method
    called on the attribute being accessed is something we might find in a queryset, we'll
    warn.
    """
    quack = False

    if node.attrname.endswith('_set'):
        # if this is a X_set method, that's a pretty strong signal that this is the default
        # Django name, rather than one set by related_name
        quack = True
    else:
        # we will
        if isinstance(node.parent, Getattr):
            func_name = getattr(node.parent, 'attrname', None)

            # Note: it would have been nice to import the Manager object from Django and
            # get its attributes that way - and this used to be the method - but unfortunately
            # there's no guarantee that Django is properly configured at that stage, and importing
            # anything from the django.db package causes an ImproperlyConfigured exception.
            # Therefore we'll fall back on a hard-coded list of attributes which won't be as accurate,
            # but this is not 100% accurate anyway.
            manager_attrs = (
                'none',
                'all',
                'count',
                'dates',
                'distinct',
                'extra',
                'get',
                'get_or_create',
                'create',
                'bulk_create',
                'filter',
                'aggregate',
                'annotate',
                'complex_filter',
                'exclude',
                'in_bulk',
                'iterator',
                'latest',
                'order_by',
                'select_for_update',
                'select_related',
                'prefetch_related',
                'values',
                'values_list',
                'update',
                'reverse',
                'defer',
                'only',
                'using',
                'exists',
            )

            if func_name in manager_attrs:
                quack = True

    if quack:
        children = list(node.get_children())
        for child in children:
            try:
                inferred = child.infered()
            except InferenceError:
                pass
            else:
                for cls in inferred:
                    if node_is_subclass(cls, 'django.db.models.base.Model'):
                        # This means that we are looking at a subclass of models.Model
                        # and something is trying to access a <something>_set attribute.
                        # Since this could exist, we will return so as not to raise an
                        # error.
                        return
    chain()
コード例 #46
0
def is_model_admin_subclass(node):
    """Checks that node is derivative of ModelAdmin class."""
    if node.name[-5:] != 'Admin' or isinstance(node.parent, ClassDef):
        return False

    return node_is_subclass(node, 'django.contrib.admin.options.ModelAdmin')