Passed
Push — master ( 65c5ff...76b686 )
by Swen
01:40
created

PostgresQuery.rename_annotations()   A

Complexity

Conditions 3

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 6.28

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
dl 0
loc 23
ccs 2
cts 7
cp 0.2857
crap 6.28
rs 9.0856
1 1
from typing import List, Tuple, Optional, Dict, Any
0 ignored issues
show
Configuration introduced by
The import typing could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
2 1
from enum import Enum
3
4 1
from django.db import models
0 ignored issues
show
Configuration introduced by
The import django.db could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
5 1
from django.db.models import sql
0 ignored issues
show
Configuration introduced by
The import django.db.models could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
6 1
from django.db.models.constants import LOOKUP_SEP
0 ignored issues
show
Configuration introduced by
The import django.db.models.constants could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7 1
from django.core.exceptions import SuspiciousOperation
0 ignored issues
show
Configuration introduced by
The import django.core.exceptions could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8
9 1
from .fields import HStoreField
10 1
from .expressions import HStoreColumn
11 1
from .datastructures import ConditionalJoin
12
13
14 1
class ConflictAction(Enum):
15
    """Possible actions to take on a conflict."""
16
17 1
    NOTHING = 'NOTHING'
18 1
    UPDATE = 'UPDATE'
19
20
21 1
class PostgresQuery(sql.Query):
0 ignored issues
show
Coding Style introduced by
This class has no __init__ method.
Loading history...
22 1
    def rename_annotations(self, annotations) -> None:
23
        """Renames the aliases for the specified annotations:
24
25
            .annotate(myfield=F('somestuf__myfield'))
26
            .rename_annotations(myfield='field')
27
28
        Arguments:
29
            annotations:
30
                The annotations to rename. Mapping the
31
                old name to the new name.
32
        """
33
34 1
        for old_name, new_name in annotations.items():
35
            annotation = self.annotations.get(old_name)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named annotations.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
36
37
            if not annotation:
38
                raise SuspiciousOperation((
39
                    'Cannot rename annotation "{old_name}" to "{new_name}", because there'
40
                    ' is no annotation named "{old_name}".'
41
                ).format(old_name=old_name, new_name=new_name))
42
43
            del self.annotations[old_name]
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named annotations.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
44
            self.annotations[new_name] = annotation
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named annotations.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
45
46 1
    def add_join_conditions(self, conditions: Dict[str, Any]) -> None:
47
        """Adds an extra condition to an existing JOIN.
48
49
        This allows you to for example do:
50
51
            INNER JOIN othertable ON (mytable.id = othertable.other_id AND [extra conditions])
52
53
        This does not work if nothing else in your query doesn't already generate the
54
        initial join in the first place.
55
        """
56
57
        alias = self.get_initial_alias()
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named get_initial_alias.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
58
        opts = self.get_meta()
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named get_meta.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
59
60
        for name, value in conditions.items():
61
            parts = name.split(LOOKUP_SEP)
62
            _, targets, _, joins, path = self.setup_joins(parts, opts, alias, allow_many=True)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named setup_joins.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
63
            self.trim_joins(targets, joins, path)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named trim_joins.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
64
65
            target_table = joins[-1]
66
            field = targets[-1]
67
            join = self.alias_map.get(target_table)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named alias_map.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
68
69
            if not join:
70
                raise SuspiciousOperation((
71
                    'Cannot add an extra join condition for "%s", there\'s no'
72
                    ' existing join to add it to.'
73
                ) % target_table)
74
75
            # convert the Join object into a ConditionalJoin object, which
76
            # allows us to add the extra condition
77
            if not isinstance(join, ConditionalJoin):
78
                self.alias_map[target_table] = ConditionalJoin.from_join(join)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named alias_map.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
79
                join = self.alias_map[target_table]
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named alias_map.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
80
81
            join.add_condition(field, value)
82
83 1
    def add_fields(self, field_names: List[str], allow_m2m: bool=True) -> bool:
0 ignored issues
show
Comprehensibility introduced by
This function exceeds the maximum number of variables (18/15).
Loading history...
84
        """
85
        Adds the given (model) fields to the select set. The field names are
86
        added in the order specified.
87
88
        This overrides the base class's add_fields method. This is called by
89
        the .values() or .values_list() method of the query set. It instructs
90
        the ORM to only select certain values. A lot of processing is neccesarry
91
        because it can be used to easily do joins. For example, `my_fk__name` pulls
92
        in the `name` field in foreign key `my_fk`.
93
94
        In our case, we want to be able to do `title__en`, where `title` is a HStoreField
95
        and `en` a key. This doesn't really involve a join. We iterate over the specified
96
        field names and filter out the ones that refer to HStoreField and compile it into
97
        an expression which is added to the list of to be selected fields using `self.add_select`.
98
        """
99
100 1
        alias = self.get_initial_alias()
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named get_initial_alias.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
101 1
        opts = self.get_meta()
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named get_meta.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
102 1
        cols = []
103 1
        for name in field_names:
104 1
            parts = name.split(LOOKUP_SEP)
105
106
            # it cannot be a special hstore thing if there's no __ in it
107 1
            if len(parts) > 1:
108 1
                column_name, hstore_key = parts[:2]
109 1
                is_hstore, field = self._is_hstore_field(column_name)
110 1
                if is_hstore:
111 1
                    cols.append(
112
                        HStoreColumn(self.model._meta.db_table or self.model.name, field, hstore_key)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _meta was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named model.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
113
                    )
114 1
                    continue
115
116 1
            _, targets, _, joins, path = self.setup_joins(parts, opts, alias, allow_many=allow_m2m)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named setup_joins.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
117 1
            targets, final_alias, joins = self.trim_joins(targets, joins, path)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named trim_joins.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
118
119 1
            for target in targets:
120 1
                cols.append(target.get_col(final_alias))
121 1
        if cols:
122 1
            self.set_select(cols)
0 ignored issues
show
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named set_select.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
123
124 1
    def _is_hstore_field(self, field_name: str) -> Tuple[bool, Optional[models.Field]]:
125
        """Gets whether the field with the specified name is a
126
        HStoreField.
127
128
        Returns
129
            A tuple of a boolean indicating whether the field
130
            with the specified name is a HStoreField, and the
131
            field instance.
132
        """
133
134 1
        field_instance = None
135 1
        for field in self.model._meta.local_concrete_fields:
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _meta was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
Bug introduced by
The Instance of PostgresQuery does not seem to have a member named model.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
136 1
            if field.name == field_name or field.column == field_name:
137 1
                field_instance = field
138 1
                break
139
140 1
        return isinstance(field_instance, HStoreField), field_instance
141
142
143 1
class PostgresInsertQuery(sql.InsertQuery):
144
    """Insert query using PostgreSQL."""
145
146 1
    def __init__(self, *args, **kwargs):
147
        """Initializes a new instance :see:PostgresInsertQuery."""
148
149 1
        super(PostgresInsertQuery, self).__init__(*args, **kwargs)
150
151 1
        self.conflict_target = []
152 1
        self.conflict_action = ConflictAction.UPDATE
153
154 1
        self.update_fields = []
155
156 1
    def values(self, objs: List, insert_fields: List, update_fields: List=[]):
0 ignored issues
show
Bug Best Practice introduced by
The default value [] might cause unintended side-effects.

Objects as default values are only created once in Python and not on each invocation of the function. If the default object is modified, this modification is carried over to the next invocation of the method.

# Bad:
# If array_param is modified inside the function, the next invocation will
# receive the modified object.
def some_function(array_param=[]):
    # ...

# Better: Create an array on each invocation
def some_function(array_param=None):
    array_param = array_param or []
    # ...
Loading history...
157
        """Sets the values to be used in this query.
158
159
        Insert fields are fields that are definitely
160
        going to be inserted, and if an existing row
161
        is found, are going to be overwritten with the
162
        specified value.
163
164
        Update fields are fields that should be overwritten
165
        in case an update takes place rather than an insert.
166
        If we're dealing with a INSERT, these will not be used.
167
168
        Arguments:
169
            objs:
170
                The objects to apply this query to.
171
172
            insert_fields:
173
                The fields to use in the INSERT statement
174
175
            update_fields:
176
                The fields to only use in the UPDATE statement.
177
        """
178
179 1
        self.insert_values(insert_fields, objs, raw=False)
0 ignored issues
show
Bug introduced by
The Instance of PostgresInsertQuery does not seem to have a member named insert_values.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
180
        self.update_fields = update_fields
181