Exemple #1
0
    def run_with_model_cls(self, model_cls: Type[Model]) -> None:
        if "_default_manager" in self.model_classdef.info.names:
            return None

        default_manager_cls = model_cls._meta.default_manager.__class__
        default_manager_fullname = helpers.get_class_fullname(
            default_manager_cls)
        try:
            default_manager_info = self.lookup_typeinfo_or_incomplete_defn_error(
                default_manager_fullname)
        except helpers.IncompleteDefnException as exc:
            # Check if default manager could be a generated manager
            base_manager_fullname = helpers.get_class_fullname(
                default_manager_cls.__bases__[0])
            generated_manager_info = self.get_generated_manager_info(
                default_manager_fullname, base_manager_fullname)
            if generated_manager_info is None:
                # Manager doesn't appear to be generated. Unless we're on the final round,
                # see if another round could help figuring out the default manager type
                if not self.api.final_iteration:
                    raise exc
                else:
                    return None
            default_manager_info = generated_manager_info

        default_manager = Instance(default_manager_info,
                                   [Instance(self.model_classdef.info, [])])
        self.add_new_node_to_model_class("_default_manager", default_manager)
Exemple #2
0
    def run_with_model_cls(self, model_cls: Type[Model]) -> None:
        for manager_name, manager in model_cls._meta.managers_map.items():
            manager_fullname = helpers.get_class_fullname(manager.__class__)
            manager_info = self.lookup_typeinfo_or_incomplete_defn_error(manager_fullname)

            if manager_name not in self.model_classdef.info.names:
                manager_type = Instance(manager_info, [Instance(self.model_classdef.info, [])])
                self.add_new_node_to_model_class(manager_name, manager_type)
            else:
                # create new MODELNAME_MANAGERCLASSNAME class that represents manager parametrized with current model
                has_manager_any_base = any(self._is_manager_any(base) for base in manager_info.bases)
                if has_manager_any_base:
                    custom_model_manager_name = manager.model.__name__ + '_' + manager.__class__.__name__
                    bases = []
                    for original_base in manager_info.bases:
                        if self._is_manager_any(original_base):
                            if original_base.type is None:
                                if not self.api.final_iteration:
                                    self.api.defer()
                            original_base = helpers.reparametrize_instance(original_base,
                                                                           [Instance(self.model_classdef.info, [])])
                        bases.append(original_base)
                    current_module = self.api.modules[self.model_classdef.info.module_name]
                    custom_manager_info = helpers.add_new_class_for_module(current_module,
                                                                           custom_model_manager_name,
                                                                           bases=bases,
                                                                           fields=OrderedDict())
                    custom_manager_type = Instance(custom_manager_info, [Instance(self.model_classdef.info, [])])
                    self.add_new_node_to_model_class(manager_name, custom_manager_type)

        # add _default_manager
        if '_default_manager' not in self.model_classdef.info.names:
            default_manager_fullname = helpers.get_class_fullname(model_cls._meta.default_manager.__class__)
            default_manager_info = self.lookup_typeinfo_or_incomplete_defn_error(default_manager_fullname)
            default_manager = Instance(default_manager_info, [Instance(self.model_classdef.info, [])])
            self.add_new_node_to_model_class('_default_manager', default_manager)

        # add related managers
        for relation in self.django_context.get_model_relations(model_cls):
            attname = relation.get_accessor_name()
            if attname is None:
                # no reverse accessor
                continue

            related_model_info = self.lookup_class_typeinfo_or_incomplete_defn_error(relation.related_model)

            if isinstance(relation, OneToOneRel):
                self.add_new_node_to_model_class(attname, Instance(related_model_info, []))
                continue

            if isinstance(relation, (ManyToOneRel, ManyToManyRel)):
                manager_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.RELATED_MANAGER_CLASS_FULLNAME)
                self.add_new_node_to_model_class(attname,
                                                 Instance(manager_info, [Instance(related_model_info, [])]))
                continue
Exemple #3
0
    def run_with_model_cls(self, model_cls: Type[Model]) -> None:
        manager_info: Optional[TypeInfo]

        encountered_incomplete_manager_def = False
        for manager_name, manager in model_cls._meta.managers_map.items():
            manager_class_name = manager.__class__.__name__
            manager_fullname = helpers.get_class_fullname(manager.__class__)
            try:
                manager_info = self.lookup_typeinfo_or_incomplete_defn_error(
                    manager_fullname)
            except helpers.IncompleteDefnException as exc:
                # Check if manager is a generated (dynamic class) manager
                base_manager_fullname = helpers.get_class_fullname(
                    manager.__class__.__bases__[0])
                manager_info = self.get_generated_manager_info(
                    manager_fullname, base_manager_fullname)
                if manager_info is None:
                    # Manager doesn't appear to be generated. Track that we encountered an
                    # incomplete definition and skip
                    encountered_incomplete_manager_def = True
                    continue
                _, manager_class_name = manager_info.fullname.rsplit(
                    ".", maxsplit=1)

            if manager_name not in self.model_classdef.info.names:
                manager_type = Instance(
                    manager_info, [Instance(self.model_classdef.info, [])])
                self.add_new_node_to_model_class(manager_name, manager_type)
            else:
                # Ending up here could for instance be due to having a custom _Manager_
                # that is not built from a custom QuerySet. Another example is a
                # related manager.
                # Don't interfere with dynamically generated manager classes
                is_dynamically_generated = "django" in manager_info.metadata and manager_info.metadata[
                    "django"].get("from_queryset_manager")
                if not self.has_any_parametrized_manager_as_base(
                        manager_info) or is_dynamically_generated:
                    continue

                custom_model_manager_name = manager.model.__name__ + "_" + manager_class_name
                try:
                    custom_manager_type = self.create_new_model_parametrized_manager(
                        custom_model_manager_name,
                        base_manager_info=manager_info)
                except helpers.IncompleteDefnException:
                    continue

                self.add_new_node_to_model_class(manager_name,
                                                 custom_manager_type)

        if encountered_incomplete_manager_def and not self.api.final_iteration:
            #  Unless we're on the final round, see if another round could figuring out all manager types
            raise helpers.IncompleteDefnException()
Exemple #4
0
 def run_with_model_cls(self, model_cls: Type[Model]) -> None:
     # add _default_manager
     if '_default_manager' not in self.model_classdef.info.names:
         default_manager_fullname = helpers.get_class_fullname(model_cls._meta.default_manager.__class__)
         default_manager_info = self.lookup_typeinfo_or_incomplete_defn_error(default_manager_fullname)
         default_manager = Instance(default_manager_info, [Instance(self.model_classdef.info, [])])
         self.add_new_node_to_model_class('_default_manager', default_manager)
Exemple #5
0
def return_proper_field_type_from_get_field(
        ctx: MethodContext, django_context: DjangoContext) -> MypyType:
    # Options instance
    assert isinstance(ctx.type, Instance)

    model_type = ctx.type.args[0]
    if not isinstance(model_type, Instance):
        return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)

    model_cls = django_context.get_model_class_by_fullname(
        model_type.type.fullname())
    if model_cls is None:
        return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)

    field_name_expr = helpers.get_call_argument_by_name(ctx, 'field_name')
    if field_name_expr is None:
        return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)

    field_name = helpers.resolve_string_attribute_value(
        field_name_expr, ctx, django_context)
    if field_name is None:
        return _get_field_instance(ctx, fullnames.FIELD_FULLNAME)

    try:
        field = model_cls._meta.get_field(field_name)
    except FieldDoesNotExist as exc:
        ctx.api.fail(exc.args[0], ctx.context)
        return AnyType(TypeOfAny.from_error)

    field_fullname = helpers.get_class_fullname(field.__class__)
    return _get_field_instance(ctx, field_fullname)
Exemple #6
0
def get_type_of_settings_attribute(ctx: AttributeContext,
                                   django_context: DjangoContext) -> MypyType:
    assert isinstance(ctx.context, MemberExpr)
    setting_name = ctx.context.name
    if not hasattr(django_context.settings, setting_name):
        ctx.api.fail(f"'Settings' object has no attribute {setting_name!r}",
                     ctx.context)
        return ctx.default_attr_type

    typechecker_api = helpers.get_typechecker_api(ctx)

    # first look for the setting in the project settings file, then global settings
    settings_module = typechecker_api.modules.get(
        django_context.django_settings_module)
    global_settings_module = typechecker_api.modules.get(
        'django.conf.global_settings')
    for module in [settings_module, global_settings_module]:
        if module is not None:
            sym = module.names.get(setting_name)
            if sym is not None and sym.type is not None:
                return sym.type

    # if by any reason it isn't present there, get type from django settings
    value = getattr(django_context.settings, setting_name)
    value_fullname = helpers.get_class_fullname(value.__class__)

    value_info = helpers.lookup_fully_qualified_typeinfo(
        typechecker_api, value_fullname)
    if value_info is None:
        return ctx.default_attr_type

    return Instance(value_info, [])
Exemple #7
0
    def run_with_model_cls(self, model_cls: Type[Model]) -> None:
        for manager_name, manager in model_cls._meta.managers_map.items():
            manager_fullname = helpers.get_class_fullname(manager.__class__)
            manager_info = self.lookup_typeinfo_or_incomplete_defn_error(manager_fullname)

            if manager_name not in self.model_classdef.info.names:
                manager_type = Instance(manager_info, [Instance(self.model_classdef.info, [])])
                self.add_new_node_to_model_class(manager_name, manager_type)
            else:
                # creates new MODELNAME_MANAGERCLASSNAME class that represents manager parametrized with current model
                has_manager_any_base = any(self._is_manager_any(base) for base in manager_info.bases)
                if has_manager_any_base:
                    custom_model_manager_name = manager.model.__name__ + '_' + manager.__class__.__name__
                    bases = []
                    for original_base in manager_info.bases:
                        if self._is_manager_any(original_base):
                            if original_base.type is None:
                                raise helpers.IncompleteDefnException()

                            original_base = helpers.reparametrize_instance(original_base,
                                                                           [Instance(self.model_classdef.info, [])])
                        bases.append(original_base)
                    current_module = self.api.modules[self.model_classdef.info.module_name]
                    custom_manager_info = helpers.add_new_class_for_module(current_module,
                                                                           custom_model_manager_name,
                                                                           bases=bases,
                                                                           fields=OrderedDict())
                    custom_manager_type = Instance(custom_manager_info, [Instance(self.model_classdef.info, [])])
                    self.add_new_node_to_model_class(manager_name, custom_manager_type)
Exemple #8
0
 def try_generate_related_manager(
         self, related_model_cls: Type[Model],
         related_model_info: TypeInfo) -> Optional[Instance]:
     manager = related_model_cls._meta.managers_map["objects"]
     base_manager_fullname = helpers.get_class_fullname(
         manager.__class__.__bases__[0])
     manager_fullname = helpers.get_class_fullname(manager.__class__)
     generated_managers = self.get_generated_manager_mappings(
         base_manager_fullname)
     if manager_fullname in generated_managers:
         real_manager_fullname = generated_managers[manager_fullname]
         manager_info = self.lookup_typeinfo(real_manager_fullname)
         if manager_info:
             return Instance(manager_info,
                             [Instance(related_model_info, [])])
     return None
Exemple #9
0
    def run_with_model_cls(self, model_cls: Type[Model]) -> None:
        manager_info: Optional[TypeInfo]

        for manager_name, manager in model_cls._meta.managers_map.items():
            manager_class_name = manager.__class__.__name__
            manager_fullname = helpers.get_class_fullname(manager.__class__)
            try:
                manager_info = self.lookup_typeinfo_or_incomplete_defn_error(
                    manager_fullname)
            except helpers.IncompleteDefnException as exc:
                if not self.api.final_iteration:
                    raise exc
                else:
                    base_manager_fullname = helpers.get_class_fullname(
                        manager.__class__.__bases__[0])
                    generated_managers = self.get_generated_manager_mappings(
                        base_manager_fullname)
                    if manager_fullname not in generated_managers:
                        # not a generated manager, continue with the loop
                        continue
                    real_manager_fullname = generated_managers[
                        manager_fullname]
                    manager_info = self.lookup_typeinfo(real_manager_fullname)
                    if manager_info is None:
                        continue
                    manager_class_name = real_manager_fullname.rsplit(
                        ".", maxsplit=1)[1]

            if manager_name not in self.model_classdef.info.names:
                manager_type = Instance(
                    manager_info, [Instance(self.model_classdef.info, [])])
                self.add_new_node_to_model_class(manager_name, manager_type)
            else:
                # creates new MODELNAME_MANAGERCLASSNAME class that represents manager parametrized with current model
                if not self.has_any_parametrized_manager_as_base(manager_info):
                    continue

                custom_model_manager_name = manager.model.__name__ + "_" + manager_class_name
                try:
                    custom_manager_type = self.create_new_model_parametrized_manager(
                        custom_model_manager_name,
                        base_manager_info=manager_info)
                except helpers.IncompleteDefnException:
                    continue

                self.add_new_node_to_model_class(manager_name,
                                                 custom_manager_type)
Exemple #10
0
    def run_with_model_cls(self, model_cls: Type[Model]) -> None:
        auto_field = model_cls._meta.auto_field
        if auto_field and not self.model_classdef.info.has_readable_member(auto_field.attname):
            # autogenerated field
            auto_field_fullname = helpers.get_class_fullname(auto_field.__class__)
            auto_field_info = self.lookup_typeinfo_or_incomplete_defn_error(auto_field_fullname)

            set_type, get_type = fields.get_field_descriptor_types(auto_field_info, is_nullable=False)
            self.add_new_node_to_model_class(auto_field.attname, Instance(auto_field_info, [set_type, get_type]))
Exemple #11
0
def get_user_model_hook(ctx: FunctionContext,
                        django_context: DjangoContext) -> MypyType:
    auth_user_model = django_context.settings.AUTH_USER_MODEL
    model_cls = django_context.apps_registry.get_model(auth_user_model)
    model_cls_fullname = helpers.get_class_fullname(model_cls)

    model_info = helpers.lookup_fully_qualified_typeinfo(
        helpers.get_typechecker_api(ctx), model_cls_fullname)
    if model_info is None:
        return AnyType(TypeOfAny.unannotated)

    return TypeType(Instance(model_info, []))
Exemple #12
0
    def create_autofield(
        self,
        auto_field: Field,
        dest_name: str,
        existing_field: bool,
    ) -> None:
        if existing_field:
            auto_field_fullname = helpers.get_class_fullname(auto_field.__class__)
            auto_field_info = self.lookup_typeinfo_or_incomplete_defn_error(auto_field_fullname)

            set_type, get_type = fields.get_field_descriptor_types(
                auto_field_info,
                is_set_nullable=True,
                is_get_nullable=False,
            )

            self.add_new_node_to_model_class(dest_name, Instance(auto_field_info, [set_type, get_type]))
Exemple #13
0
def return_proper_field_type_from_get_field(
        ctx: MethodContext, django_context: DjangoContext) -> MypyType:
    # Options instance
    assert isinstance(ctx.type, Instance)

    # bail if list of generic params is empty
    if len(ctx.type.args) == 0:
        return ctx.default_return_type

    model_type = ctx.type.args[0]
    if not isinstance(model_type, Instance):
        return ctx.default_return_type

    model_cls = django_context.get_model_class_by_fullname(
        model_type.type.fullname)
    if model_cls is None:
        return ctx.default_return_type

    field_name_expr = helpers.get_call_argument_by_name(ctx, 'field_name')
    if field_name_expr is None:
        return ctx.default_return_type

    field_name = helpers.resolve_string_attribute_value(
        field_name_expr, django_context)
    if field_name is None:
        return ctx.default_return_type

    try:
        field = model_cls._meta.get_field(field_name)
    except FieldDoesNotExist as exc:
        # if model is abstract, do not raise exception, skip false positives
        if not model_cls._meta.abstract:
            ctx.api.fail(exc.args[0], ctx.context)
        return AnyType(TypeOfAny.from_error)

    field_fullname = helpers.get_class_fullname(field.__class__)
    return _get_field_instance(ctx, field_fullname)
Exemple #14
0
 def all_registered_model_class_fullnames(self) -> Set[str]:
     return {
         helpers.get_class_fullname(cls)
         for cls in self.all_registered_model_classes
     }
Exemple #15
0
 def lookup_class_typeinfo_or_incomplete_defn_error(self, klass: type) -> TypeInfo:
     fullname = helpers.get_class_fullname(klass)
     field_info = self.lookup_typeinfo_or_incomplete_defn_error(fullname)
     return field_info