Passed
Push — master ( db4324...def7da )
by Swen
01:53
created

LocalizedValue.translate()   A

Complexity

Conditions 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
rs 9.4285
ccs 10
cts 10
cp 1
cc 3
crap 3
1 1
import collections
2
3 1
from typing import Optional
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...
4
5 1
from django.conf import settings
0 ignored issues
show
Configuration introduced by
The import django.conf 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.utils import translation
0 ignored issues
show
Configuration introduced by
The import django.utils 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
8
9 1
class LocalizedValue(dict):
10
    """Represents the value of a :see:LocalizedField."""
11 1
    default_value = None
12
13 1
    def __init__(self, keys: dict=None):
14
        """Initializes a new instance of :see:LocalizedValue.
15
16
        Arguments:
17
            keys:
18
                The keys to initialize this value with. Every
19
                key contains the value of this field in a
20
                different language.
21
        """
22
23 1
        super().__init__({})
24 1
        self._interpret_value(keys)
25
26 1
    def get(self, language: str=None, default: str=None) -> str:
27
        """Gets the underlying value in the specified or
28
        primary language.
29
30
        Arguments:
31
            language:
32
                The language to get the value in.
33
34
        Returns:
35
            The value in the current language, or
36
            the primary language in case no language
37
            was specified.
38
        """
39
40 1
        language = language or settings.LANGUAGE_CODE
41 1
        return super().get(language, default)
42
43 1
    def set(self, language: str, value: str):
44
        """Sets the value in the specified language.
45
46
        Arguments:
47
            language:
48
                The language to set the value in.
49
50
            value:
51
                The value to set.
52
        """
53
54 1
        self[language] = value
55 1
        self.__dict__.update(self)
56 1
        return self
57
58 1
    def deconstruct(self) -> dict:
59
        """Deconstructs this value into a primitive type.
60
61
        Returns:
62
            A dictionary with all the localized values
63
            contained in this instance.
64
        """
65
66 1
        path = 'localized_fields.value.%s' % self.__class__.__name__
67 1
        return path, [self.__dict__], {}
68
69 1
    def _interpret_value(self, value):
70
        """Interprets a value passed in the constructor as
71
        a :see:LocalizedValue.
72
73
        If string:
74
            Assumes it's the default language.
75
76
        If dict:
77
            Each key is a language and the value a string
78
            in that language.
79
80
        If list:
81
            Recurse into to apply rules above.
82
83
        Arguments:
84
            value:
85
                The value to interpret.
86
        """
87
88 1
        for lang_code, _ in settings.LANGUAGES:
89 1
            self.set(lang_code, self.default_value)
90
91 1
        if isinstance(value, str):
92 1
            self.set(settings.LANGUAGE_CODE, value)
93
94 1
        elif isinstance(value, dict):
95 1
            for lang_code, _ in settings.LANGUAGES:
96 1
                lang_value = value.get(lang_code, self.default_value)
97 1
                self.set(lang_code, lang_value)
98
99 1
        elif isinstance(value, collections.Iterable):
100 1
            for val in value:
101 1
                self._interpret_value(val)
102
103 1
    def translate(self) -> Optional[str]:
104
        """Gets the value in the current language or falls
105
        back to the next language if there's no value in the
106
        current language."""
107
108 1
        fallbacks = getattr(settings, 'LOCALIZED_FIELDS_FALLBACKS', {})
109
110 1
        language = translation.get_language() or settings.LANGUAGE_CODE
111 1
        languages = fallbacks.get(language, [settings.LANGUAGE_CODE])[:]
112 1
        languages.insert(0, language)
113
114 1
        for lang_code in languages:
115 1
            value = self.get(lang_code)
116 1
            if value:
117 1
                return value or None
118
119 1
        return None
120
121 1
    def __str__(self) -> str:
122
        """Gets the value in the current language or falls
123
        back to the next language if there's no value in the
124
        current language."""
125
126 1
        return self.translate() or ''
127
128 1
    def __eq__(self, other):
129
        """Compares :paramref:self to :paramref:other for
130
        equality.
131
132
        Returns:
133
            True when :paramref:self is equal to :paramref:other.
134
            And False when they are not.
135
        """
136
137 1
        if not isinstance(other, type(self)):
138 1
            if isinstance(other, str):
139 1
                return self.__str__() == other
140 1
            return False
141
142 1
        for lang_code, _ in settings.LANGUAGES:
143 1
            if self.get(lang_code) != other.get(lang_code):
144 1
                return False
145
146 1
        return True
147
148 1
    def __ne__(self, other):
149
        """Compares :paramref:self to :paramerf:other for
150
        in-equality.
151
152
        Returns:
153
            True when :paramref:self is not equal to :paramref:other.
154
            And False when they are.
155
        """
156
157 1
        return not self.__eq__(other)
158
159 1
    def __setattr__(self, language: str, value: str):
160
        """Sets the value for a language with the specified name.
161
162
        Arguments:
163
            language:
164
                The language to set the value in.
165
166
            value:
167
                The value to set.
168
        """
169
170 1
        self.set(language, value)
171
172
    def __repr__(self):  # pragma: no cover
173
        """Gets a textual representation of this object."""
174
175
        return '%s<%s> 0x%s' % (self.__class__.__name__,
176
                                self.__dict__, id(self))
177
178
179 1
class LocalizedStringValue(LocalizedValue):
180 1
    default_value = ''
181
182
183 1
class LocalizedFileValue(LocalizedValue):
184 1
    def __getattr__(self, name: str):
185
        """Proxies access to attributes to attributes of LocalizedFile"""
186
187 1
        value = self.get(translation.get_language())
188 1
        if hasattr(value, name):
189 1
            return getattr(value, name)
190 1
        raise AttributeError("'{}' object has no attribute '{}'".
191
                             format(self.__class__.__name__, name))
192
193 1
    def __str__(self) -> str:
194
        """Returns string representation of value"""
195 1
        return str(super().__str__())
196
197 1
    def localized(self):
198
        """Returns value for current language"""
199
        return self.get(translation.get_language())
200