Passed
Pull Request — master (#259)
by Piotr
01:48
created

ObjDict.__getattribute__()   B

Complexity

Conditions 6

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
c 2
b 0
f 0
dl 0
loc 16
rs 8
1
import warnings
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
Unused Code introduced by
The import warnings seems to be unused.
Loading history...
2
3
from django.conf import settings as django_settings
0 ignored issues
show
introduced by
Unable to import 'django.conf'
Loading history...
4
from django.core.exceptions import ImproperlyConfigured
0 ignored issues
show
introduced by
Unable to import 'django.core.exceptions'
Loading history...
Unused Code introduced by
Unused ImproperlyConfigured imported from django.core.exceptions
Loading history...
5
from django.test.signals import setting_changed
0 ignored issues
show
introduced by
Unable to import 'django.test.signals'
Loading history...
6
from django.utils import six
0 ignored issues
show
introduced by
Unable to import 'django.utils'
Loading history...
7
from django.utils.functional import LazyObject
0 ignored issues
show
introduced by
Unable to import 'django.utils.functional'
Loading history...
8
from django.utils.module_loading import import_string
0 ignored issues
show
introduced by
Unable to import 'django.utils.module_loading'
Loading history...
9
10
11
DJOSER_SETTINGS_NAMESPACE = 'DJOSER'
12
13
14
class ObjDict(dict):
0 ignored issues
show
Coding Style introduced by
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
15
    def __getattribute__(self, item):
16
        try:
17
            is_list_of_strings = (
18
                isinstance(self[item], list) and
19
                all(isinstance(elem, str) for elem in self[item])
20
            )
21
22
            if is_list_of_strings:
23
                self[item] = [import_string(func) for func in self[item]]
24
            elif isinstance(self[item], str):
25
                self[item] = import_string(self[item])
26
            value = self[item]
27
        except KeyError:
28
            value = super(ObjDict, self).__getattribute__(item)
29
30
        return value
31
32
33
default_settings = {
0 ignored issues
show
Coding Style Naming introduced by
The name default_settings does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
34
    'PASSWORD_UPDATE_REQUIRE_RETYPE': False,
35
    'USERNAME_UPDATE_REQUIRE_RETYPE': False,
36
    'PASSWORD_RESET_CONFIRM_REQUIRE_RETYPE': False,
37
    'PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND': False,
38
    'PASSWORD_VALIDATORS': [],
39
    'LOGOUT_ON_PASSWORD_CHANGE': False,
40
    'SOCIAL_AUTH_TOKEN_STRATEGY': 'djoser.social.token.jwt.TokenStrategy',
41
    'SOCIAL_AUTH_ALLOWED_REDIRECT_URIS': [],
42
    'TOKEN_MODEL': None,
43
44
    'PIPELINES': ObjDict({
45
        'user_activate': [
46
            'djoser.pipelines.user_activate.serialize_request',
47
            'djoser.pipelines.user_activate.perform',
48
            'djoser.pipelines.user_activate.signal',
49
            'djoser.pipelines.email.confirmation_email',
50
        ],
51
        'user_create': [
52
            'djoser.pipelines.user_create.serialize_request',
53
            'djoser.pipelines.user_create.perform',
54
            'djoser.pipelines.user_create.serialize_instance',
55
            'djoser.pipelines.user_create.signal',
56
            'djoser.pipelines.email.activation_email',
57
        ],
58
        'user_update': [
59
            'djoser.pipelines.user_update.serialize_request',
60
            'djoser.pipelines.user_update.perform',
61
            'djoser.pipelines.user_update.signal',
62
            'djoser.pipelines.user_update.serialize_instance',
63
        ],
64
        'user_delete': [
65
            'djoser.pipelines.user_delete.serialize_request',
66
            'djoser.pipelines.user_delete.perform',
67
            'djoser.pipelines.user_delete.signal',
68
        ],
69
        'user_detail': [
70
            'djoser.pipelines.user_detail.perform',
71
            'djoser.pipelines.user_detail.serialize_instance',
72
        ],
73
        'username_update': [
74
            'djoser.pipelines.username_update.serialize_request',
75
            'djoser.pipelines.username_update.perform',
76
            'djoser.pipelines.username_update.signal',
77
        ],
78
        'password_update': [
79
            'djoser.pipelines.password_update.serialize_request',
80
            'djoser.pipelines.password_update.perform',
81
            'djoser.pipelines.password_update.signal',
82
        ],
83
        'password_reset': [
84
            'djoser.pipelines.password_reset.serialize_request',
85
            'djoser.pipelines.password_reset.perform',
86
        ],
87
        'password_reset_confirm': [
88
            'djoser.pipelines.password_reset_confirm.serialize_request',
89
            'djoser.pipelines.password_reset_confirm.perform',
90
            'djoser.pipelines.password_reset_confirm.signal',
91
        ],
92
        'token_create': [
93
            'djoser.pipelines.token_create.serialize_request',
94
            'djoser.pipelines.token_create.perform',
95
            'djoser.pipelines.token_create.signal',
96
        ],
97
        'token_destroy': [
98
            'djoser.pipelines.token_destroy.perform',
99
            'djoser.pipelines.token_destroy.signal',
100
        ]
101
    }),
102
    'SERIALIZERS': ObjDict({
103
        'user_activate':
104
            'djoser.serializers.UserActivateSerializer',
105
        'password_reset':
106
            'djoser.serializers.PasswordResetSerializer',
107
        'password_reset_confirm':
108
            'djoser.serializers.PasswordResetConfirmSerializer',
109
        'password_reset_confirm_retype':
110
            'djoser.serializers.PasswordResetConfirmRetypeSerializer',
111
        'set_password':
112
            'djoser.serializers.SetPasswordSerializer',
113
        'set_password_retype':
114
            'djoser.serializers.SetPasswordRetypeSerializer',
115
        'set_username':
116
            'djoser.serializers.SetUsernameSerializer',
117
        'set_username_retype':
118
            'djoser.serializers.SetUsernameRetypeSerializer',
119
        'user_create':
120
            'djoser.serializers.UserCreateSerializer',
121
        'user_delete':
122
            'djoser.serializers.UserDeleteSerializer',
123
        'user':
124
            'djoser.serializers.UserSerializer',
125
        'token':
126
            'djoser.serializers.TokenSerializer',
127
        'token_create':
128
            'djoser.serializers.TokenCreateSerializer',
129
    }),
130
    'EMAIL': ObjDict({
131
        'activation': 'djoser.email.ActivationEmail',
132
        'confirmation': 'djoser.email.ConfirmationEmail',
133
        'password_reset': 'djoser.email.PasswordResetEmail',
134
    }),
135
}
136
137
SETTINGS_TO_IMPORT = ['TOKEN_MODEL', 'SOCIAL_AUTH_TOKEN_STRATEGY']
138
139
140
class Settings(object):
0 ignored issues
show
Coding Style introduced by
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
141
    def __init__(self, default_settings, explicit_overriden_settings=None):
0 ignored issues
show
Comprehensibility Bug introduced by
default_settings is re-defining a name which is already available in the outer-scope (previously defined on line 33).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
Unused Code introduced by
The argument default_settings seems to be unused.
Loading history...
142
        if explicit_overriden_settings is None:
143
            explicit_overriden_settings = {}
144
145
        overriden_settings = getattr(
146
            django_settings, DJOSER_SETTINGS_NAMESPACE, {}
147
        ) or explicit_overriden_settings
148
149
        self._load_default_settings()
150
        self._override_settings(overriden_settings)
151
        self._init_settings_to_import()
152
153
    def _load_default_settings(self):
154
        for setting_name, setting_value in six.iteritems(default_settings):
155
            if setting_name.isupper():
156
                setattr(self, setting_name, setting_value)
157
158
    def _override_settings(self, overriden_settings):
159
        for setting_name, setting_value in six.iteritems(overriden_settings):
160
            value = setting_value
161
            if isinstance(setting_value, dict):
162
                value = getattr(self, setting_name, {})
163
                value.update(ObjDict(setting_value))
164
            setattr(self, setting_name, value)
165
166
    def _init_settings_to_import(self):
167
        for setting_name in SETTINGS_TO_IMPORT:
168
            value = getattr(self, setting_name)
169
            if isinstance(value, str):
170
                setattr(self, setting_name, import_string(value))
171
172
173
class LazySettings(LazyObject):
0 ignored issues
show
Coding Style introduced by
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
174
    def _setup(self, explicit_overriden_settings=None):
175
        self._wrapped = Settings(default_settings, explicit_overriden_settings)
0 ignored issues
show
Coding Style introduced by
The attribute _wrapped was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
176
177
178
settings = LazySettings()
0 ignored issues
show
Coding Style Naming introduced by
The name settings does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
179
180
181
def reload_djoser_settings(*args, **kwargs):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
Unused Code introduced by
The argument args seems to be unused.
Loading history...
182
    global settings
0 ignored issues
show
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
Coding Style Naming introduced by
The name settings does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
183
    setting, value = kwargs['setting'], kwargs['value']
184
    if setting == DJOSER_SETTINGS_NAMESPACE:
185
        settings._setup(explicit_overriden_settings=value)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _setup 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...
186
187
188
setting_changed.connect(reload_djoser_settings)
189