Passed
Push — master ( ce647f...f4ead8 )
by Dean
02:57
created

PathEnvironment.home()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.125

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 3
ccs 1
cts 2
cp 0.5
rs 10
cc 1
crap 1.125
1 1
from plugin.core.constants import PLUGIN_IDENTIFIER
2
3 1
import gettext
4 1
import locale
5 1
import logging
6 1
import os
7 1
import platform
8
9 1
DEFAULT_LOCALE = 'en_US'
10
11 1
log = logging.getLogger(__name__)
12
13
14 1
class PathEnvironment(object):
15
    # TODO confirm validity of this on *nix and OS X
16
17 1
    def __init__(self, core):
18 1
        self._core = core
19
20 1
        self._plugin_support = None
21
22 1
    @property
23
    def contents(self):
24 1
        return os.path.abspath(os.path.join(self.code, '..'))
25
26 1
    @property
27
    def code(self):
28 1
        return self._core.code_path
29
30 1
    @property
31
    def home(self):
32
        return os.path.abspath(os.path.join(self.plugin_support, '..'))
33
34 1
    @property
35
    def libraries(self):
36 1
        return os.path.join(self.contents, 'Libraries')
37
38 1
    @property
39
    def locale(self):
40
        return os.path.join(self.contents, 'Locale')
41
42 1
    @property
43
    def plugin_caches(self):
44 1
        return os.path.join(self.plugin_support, 'Caches', PLUGIN_IDENTIFIER)
45
46 1
    @property
47
    def plugin_data(self):
48 1
        return os.path.join(self.plugin_support, 'Data', PLUGIN_IDENTIFIER)
49
50 1
    @property
51
    def plugin_database(self):
52 1
        return os.path.join(self.plugin_support, 'Databases', '%s.db' % PLUGIN_IDENTIFIER)
53
54 1
    @property
55
    def plugin_support(self):
56 1
        if self._plugin_support is not None:
57 1
            return self._plugin_support
58
59
        base_path = self.code[:self.code.index(os.path.sep + 'Plug-ins')]
60
61
        return os.path.join(base_path, 'Plug-in Support')
62
63 1
    @plugin_support.setter
64
    def plugin_support(self, path):
65 1
        self._plugin_support = path
66
67
68 1
class PlatformEnvironment(object):
69 1
    def __init__(self, platform):
70 1
        self._platform = platform
71
72 1
    @property
73
    def machine_identifier(self):
74
        return self._platform.MachineIdentifier
75
76 1
    @property
77
    def server_version(self):
78
        return self._platform.ServerVersion
79
80
81 1
class Environment(object):
82 1
    dict = None
83 1
    path = None
84 1
    platform = None
85 1
    prefs = None
86
87 1
    language = None
88 1
    translation = None
89
90 1
    @classmethod
91
    def setup(cls, core, dict, platform, prefs):
92 1
        cls.path = PathEnvironment(core)
93 1
        cls.dict = dict
94 1
        cls.platform = PlatformEnvironment(platform)
95 1
        cls.prefs = prefs
96
97 1
    @classmethod
98
    def setup_locale(cls):
99
        # Use language defined in preferences (if available)
100
        language = cls.get_pref('language') or ''
101
102
        # Initialize locale
103
        try:
104
            locale.setlocale(locale.LC_ALL, language)
105
        except Exception, ex:
106
            log.warn('Unable to set locale to %r: %s', language, ex, exc_info=True)
107
            return False
108
109
        # Default to the "en_US" locale
110
        code, _ = locale.getlocale()
111
112
        if not code:
113
            try:
114
                locale.setlocale(locale.LC_ALL, DEFAULT_LOCALE)
115
            except Exception, ex:
116
                log.warn('Unable to set locale to %r: %s', DEFAULT_LOCALE, ex, exc_info=True)
117
                return False
118
119
        log.info('Using locale: %r', locale.getlocale())
120
        return True
121
122 1
    @classmethod
123
    def setup_translation(cls):
124
        # Retrieve preferred language
125
        try:
126
            cls.language = cls._get_language()
127
        except Exception, ex:
128
            log.warn('Unable to retrieve preferred language: %s', ex, exc_info=True)
129
            cls.language = None
130
            return
131
132
        if not cls.language:
133
            log.warn('Unable to determine preferred language (system: %r)', platform.system())
134
            return
135
136
        # Build list of languages
137
        languages = [cls.language]
138
139
        if '_' in cls.language:
140
            languages.append(cls.language.split('_', 1)[0])
141
142
        # Check if language exists
143
        found = False
144
145
        for lang in languages:
146
            if os.path.exists(os.path.join(cls.path.locale, lang)):
147
                found = True
148
                break
149
150
        if not found:
151
            log.info('No translation available for %r', languages)
152
            return
153
154
        # Setup gettext
155
        try:
156
            cls.translation = gettext.translation(
157
                domain='channel',
158
                localedir=os.path.join(cls.path.locale),
159
                languages=languages
160
            )
161
        except Exception, ex:
162
            log.warn('Unable to initialize languages: %r - %s', languages, ex, exc_info=True)
163
            return
164
165
        log.info('Using languages: %r (translation: %r)', languages, cls.translation)
166
167 1
    @classmethod
168
    def get_pref(cls, key):
169 1
        try:
170 1
            return cls.prefs[key]
171
        except:
172
            return None
173
174 1
    @classmethod
175
    def _get_language(cls):
176
        # Use language defined in preferences (if available)
177
        language = cls.get_pref('language')
178
179
        if language:
180
            return language.lower()
181
182
        # Use system language
183
        if platform.system() == 'Windows':
184
            # Retrieve windows user language
185
            return cls._get_windows_default_language()
186
187
        # Retrieve current locale
188
        code, _ = locale.getdefaultlocale()
189
190
        # Ensure language code is valid
191
        if not code or type(code) is not str:
192
            log.info('Unable to detect system language, defaulting to the "%s" locale', DEFAULT_LOCALE)
193
            return DEFAULT_LOCALE.lower()
194
195
        # Parse language code
196
        if len(code) == 2:
197
            return code.lower()
198
        elif len(code) > 2 and code[2] == '_':
199
            return code[:5].lower()
200
201
        log.warn('Unknown language code: %r', code)
202
        return None
203
204 1
    @classmethod
205
    def _get_windows_default_language(cls):
206
        try:
207
            import ctypes
208
            lang_id = ctypes.windll.kernel32.GetUserDefaultUILanguage()
209
        except Exception, ex:
210
            log.warn('Unable to determine preferred language: %s', ex, exc_info=True)
211
            return None
212
213
        if lang_id not in locale.windows_locale:
214
            log.warn('Unknown language: %r', lang_id)
215
            return None
216
217
        return locale.windows_locale[lang_id].lower()
218
219
220 1
def translate(message):
221 1
    if Environment.translation:
222
        return Environment.translation.ugettext(message)
223
224
    return message
225