@@ -17,6 +17,11 @@ def __missing__(self, key):
17
17
return '{' + key + '}'
18
18
19
19
20
+ def addon_id ():
21
+ """Return add-on ID"""
22
+ return get_addon_info ('id' )
23
+
24
+
20
25
def addon_profile ():
21
26
"""Cache and return add-on profile"""
22
27
return to_unicode (xbmc .translatePath (ADDON .getAddonInfo ('profile' )))
@@ -178,7 +183,7 @@ def jsonrpc(*args, **kwargs):
178
183
179
184
# We do not accept both args and kwargs
180
185
if args and kwargs :
181
- log ('ERROR: Wrong use of jsonrpc()' )
186
+ log (4 , 'ERROR: Wrong use of jsonrpc()' )
182
187
return None
183
188
184
189
# Process a list of actions
@@ -198,9 +203,13 @@ def jsonrpc(*args, **kwargs):
198
203
return loads (xbmc .executeJSONRPC (dumps (kwargs )))
199
204
200
205
201
- def log (msg , level = xbmc .LOGDEBUG , ** kwargs ):
202
- ''' InputStream Helper log method '''
203
- xbmc .log (msg = from_unicode ('[{addon}] {msg}' .format (addon = get_addon_info ('id' ), msg = msg .format (** kwargs ))), level = level )
206
+ def log (level = 0 , message = '' , ** kwargs ):
207
+ """Log info messages to Kodi"""
208
+ if kwargs :
209
+ from string import Formatter
210
+ message = Formatter ().vformat (message , (), SafeDict (** kwargs ))
211
+ message = '[{addon}] {message}' .format (addon = addon_id (), message = message )
212
+ xbmc .log (from_unicode (message ), level )
204
213
205
214
206
215
def kodi_to_ascii (string ):
@@ -215,3 +224,83 @@ def kodi_to_ascii(string):
215
224
string = string .replace ('[COLOR yellow]' , '' )
216
225
string = string .replace ('[/COLOR]' , '' )
217
226
return string
227
+
228
+
229
+ def samefile (src , dest ):
230
+ """Check if file is identical"""
231
+ stat_src = stat_file (src )
232
+ stat_dest = stat_file (dest )
233
+ # Check if this is a hardlink
234
+ if (stat_src .st_dev (), stat_src .st_ino ()) == (stat_dest .st_dev (), stat_dest .st_ino ()):
235
+ return True
236
+
237
+ # Check file sizes
238
+ if stat_src .st_size () != stat_dest .st_size ():
239
+ return False
240
+
241
+ # Check if this is a symlink
242
+ from os .path import samefile as opsamefile
243
+ if opsamefile (src , dest ):
244
+ return True
245
+
246
+ # Otherwise compare content (may be slow)
247
+ with open (src , 'r' ) as srcfd , open (dest , 'r' ) as destfd :
248
+ if srcfd .read () == destfd .read ():
249
+ return True
250
+
251
+ return False
252
+
253
+
254
+ def copy (src , dest ):
255
+ """Copy a file (using xbmcvfs)"""
256
+ from xbmcvfs import copy as vfscopy
257
+ log (2 , "Copy file '{src}' to '{dest}'." , src = src , dest = dest )
258
+ return vfscopy (src , dest )
259
+
260
+
261
+ def delete (path ):
262
+ """Remove a file (using xbmcvfs)"""
263
+ from xbmcvfs import delete as vfsdelete
264
+ log (2 , "Delete file '{path}'." , path = path )
265
+ return vfsdelete (path )
266
+
267
+
268
+ def exists (path ):
269
+ """Whether the path exists (using xbmcvfs)"""
270
+ from xbmcvfs import exists as vfsexists
271
+ return vfsexists (path )
272
+
273
+
274
+ def hardlink (src , dest ):
275
+ """Hardlink a file when possible, copy when needed"""
276
+ from os import link
277
+
278
+ if exists (dest ):
279
+ delete (dest )
280
+
281
+ try :
282
+ link (src , dest )
283
+ except OSError :
284
+ return copy (src , dest )
285
+ log (2 , "Hardlink file '{src}' to '{dest}'." , src = src , dest = dest )
286
+ return True
287
+
288
+
289
+ def mkdir (path ):
290
+ """Create a directory (using xbmcvfs)"""
291
+ from xbmcvfs import mkdir as vfsmkdir
292
+ log (2 , "Create directory '{path}'." , path = path )
293
+ return vfsmkdir (path )
294
+
295
+
296
+ def mkdirs (path ):
297
+ """Create directory including parents (using xbmcvfs)"""
298
+ from xbmcvfs import mkdirs as vfsmkdirs
299
+ log (2 , "Recursively create directory '{path}'." , path = path )
300
+ return vfsmkdirs (path )
301
+
302
+
303
+ def stat_file (path ):
304
+ """Return information about a file (using xbmcvfs)"""
305
+ from xbmcvfs import Stat
306
+ return Stat (path )
0 commit comments