1
2
3 """
4 @copyright:
5 Copyright (c) 2014 by mTLD Top Level Domain Limited. All rights reserved.\n
6 Portions copyright (c) 2008 by Argo Interactive Limited.\n
7 Portions copyright (c) 2008 by Nokia Inc.\n
8 Portions copyright (c) 2008 by Telecom Italia Mobile S.p.A.\n
9 Portions copyright (c) 2008 by Volantis Systems Limited.\n
10 Portions copyright (c) 2002-2008 by Andreas Staeding.\n
11 Portions copyright (c) 2008 by Zandan.\n
12 @author: dotMobi
13 """
14
15 import os.path
16
17 from mobi.mtld.da.exception.data_file_exception import DataFileException
18 from mobi.mtld.da.device.tree import Tree
19 from mobi.mtld.da.device.config import Config
20 from mobi.mtld.da.property_name import PropertyName
21 from mobi.mtld.da.data_type import DataType
22 from mobi.mtld.da.property import Property
23 from mobi.mtld.da.properties import Properties
24
26 """
27 The DeviceAtlas Device Detection API provides a way to detect devices based on
28 the HTTP headers. Using the headers, the API returns device information such
29 as screen width, screen height, is mobile, vendor, model etc.
30
31 DeviceApi.get_properties(user_agent_or_headers, client_side_properties)
32
33 To get the most accurate results:
34 1- Pass the whole HTTP headers.
35 2- Use the DeviceAtlas client-side-component and pass the result.
36
37 Example usage:
38
39 >>> device_api = DeviceApi()
40 >>> device_api.load_data_from_file("/path/to/datafile.json")
41 >>>
42 >>> # get all properties from the headers
43 >>> properties = device_api.get_properties(headers)
44 >>>
45 >>> # .... use the properties ....
46 >>>
47 >>> if properties.contains("isMobilePhone", True):
48 >>> # it is a mobile phone
49 >>>
50 >>> if "model" in properties:
51 >>> device_model = str(properties.get("model"))
52 """
53
54 api_version = '2.0'
55
56 __config = None
57 __tree = None
58 __cached_client_side_properties = None
59 __cached_user_agent = None
60 __cached_headers = None
61 __properties = None
62
64 """
65 Constructs a DeviceApi instance with default configs. You can see the
66 default configs in the class "Configuration".
67
68 @param config: Instance of Configuration. You can change the DeviceAtlas API
69 configs by creating an instance or Configuration and setting your custom
70 config values then passing the instance to the DeviceApi constructor.
71 """
72 if config is None:
73 self.__config = Config()
74 else:
75 self.__config = config
76
78 """
79 Load the DeviceAtlas device detection data into the API from a JSON file.
80 The JSON data file is provided from the DeviceAtlas web-site.
81 @param json_data_file_path: Path to the JSON data file.
82 """
83
84 if not os.path.isfile(json_data_file_path):
85 raise DataFileException("File not found: " + json_data_file_path)
86
87 json = open(json_data_file_path, 'r').read()
88
89 self.load_data_from_string(json)
90
92 """
93 Load the DeviceAtlas device detection data into the API from a string.
94 @param json_data_string: JSON data string.
95 """
96 self.__tree = None
97 self.__tree = Tree(json_data_string, self.__config)
98
113
115 """
116 Get the device data (JSON file) version.
117 """
118 return self.__tree.data_version()
119
121 """
122 Get the device data (JSON file) revision.
123 """
124 return self.__tree.data_revision
125
131
132 - def get_properties(self, user_agent_or_headers, client_side_properties = None):
197
198
199
201 """
202 Get the Accept-Language header and add language properties to the property
203 list.
204 @param accept_language: Accept-Language header.
205 """
206
207 if accept_language is None or accept_language.replace(' ', '') == '':
208 return
209
210 langs = accept_language.split(',')
211
212 best = ''
213 q_best = 0
214
215
216 for langs_i in langs:
217
218 lang = langs_i.split(';')
219
220
221 q = 1
222
223 if len(lang) > 1:
224 s = lang[1].replace(' ', '')
225 if s[0:2] == "q=":
226 try:
227 q = float(s[2:])
228 except:
229 q = 0
230 else:
231 continue
232
233
234 locale = lang[0].replace(' ', '')
235 length = len(locale)
236
237 if (q > q_best or (q == q_best and length > 2 and length > len(best) and
238 locale[0:2] == best[0:2])):
239 best = locale
240 q_best = q
241
242 if length == 4 and q == 1:
243 break
244
245
246
247
248 if best != "*":
249 lang_locale = best.replace('_', '-').split('-')
250 lang = lang_locale[0].lower()
251 if len(lang_locale) == 2:
252 locale = lang + '-' + lang_locale[1].upper()
253 else:
254 locale = None
255
256 if lang != '':
257 property_name_language = 'language'
258 self.__tree.properties[property_name_language] = Property(lang, 's')
259 if locale is not None and len(locale) == 5:
260 property_name_language_locale = 'languageLocale'
261 self.__tree.properties[property_name_language_locale] = Property(locale,
262 's')
263
274
275
303
304
306
307 normalised_keys = {}
308 original_keys = list(headers.keys())
309
310
311 for key, value in headers.items():
312 normalised_key = key.lower().replace('_','-').replace('http-','')
313 normalised_keys[normalised_key] = value
314
315
316 for key, value in normalised_keys.items():
317 headers[key] = value
318
319
320 for key in original_keys:
321 if key not in normalised_keys:
322 headers.pop(key)
323