common.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. '''
  2. xbmcswift2.common
  3. -----------------
  4. This module contains some common helpful functions.
  5. :copyright: (c) 2012 by Jonathan Beluch
  6. :license: GPLv3, see LICENSE for more details.
  7. '''
  8. import urllib
  9. import urllib2
  10. try:
  11. import cPickle as pickle
  12. except ImportError:
  13. import pickle
  14. def xbmc_url(url, **options):
  15. '''Appends key/val pairs to the end of a URL. Useful for passing arbitrary
  16. HTTP headers to XBMC to be used when fetching a media resource, e.g.
  17. cookies.
  18. '''
  19. optionstring = urllib.urlencode(options)
  20. if optionstring:
  21. return url + '|' + optionstring
  22. return url
  23. def enum(*args, **kwargs):
  24. '''An enum class to mirror XBMC constatns. All args and kwargs.keys are
  25. added as atrrs on the returned object.
  26. >>> States = enum('NEW_JERSEY', NY='NEW_YORK')
  27. >>> States.NY
  28. 'NEW_YORK'
  29. >>> States.NEW_JERSEY
  30. 'NEW_JERSEY'
  31. >>> States._fields
  32. ['NY', 'NEW_JERSEY']
  33. '''
  34. kwargs.update((arg, arg) for arg in args)
  35. kwargs['_fields'] = kwargs.keys()
  36. return type('Enum', (), kwargs)
  37. Modes = enum('XBMC', 'ONCE', 'CRAWL', 'INTERACTIVE')
  38. DEBUG_MODES = [Modes.ONCE, Modes.CRAWL, Modes.INTERACTIVE]
  39. def clean_dict(dct):
  40. '''Returns a dict where items with a None value are removed'''
  41. return dict((key, val) for key, val in dct.items() if val is not None)
  42. def pickle_dict(items):
  43. '''Returns a new dictionary where values which aren't instances of
  44. basestring are pickled. Also, a new key '_pickled' contains a comma
  45. separated list of keys corresponding to the pickled values.
  46. '''
  47. ret = {}
  48. pickled_keys = []
  49. for key, val in items.items():
  50. if isinstance(val, basestring):
  51. ret[key] = val
  52. else:
  53. pickled_keys.append(key)
  54. ret[key] = pickle.dumps(val)
  55. if pickled_keys:
  56. ret['_pickled'] = ','.join(pickled_keys)
  57. return ret
  58. def unpickle_args(items):
  59. '''Takes a dict and unpickles values whose keys are found in
  60. '_pickled' key.
  61. >>> unpickle_args({'_pickled': ['foo']. 'foo': ['I3%0A.']})
  62. {'foo': 3}
  63. '''
  64. # Technically there can be more than one _pickled value. At this point
  65. # we'll just use the first one
  66. pickled = items.pop('_pickled', None)
  67. if pickled is None:
  68. return items
  69. pickled_keys = pickled[0].split(',')
  70. ret = {}
  71. for key, vals in items.items():
  72. if key in pickled_keys:
  73. ret[key] = [pickle.loads(val) for val in vals]
  74. else:
  75. ret[key] = vals
  76. return ret
  77. def unpickle_dict(items):
  78. '''Returns a dict pickled with pickle_dict'''
  79. pickled_keys = items.pop('_pickled', '').split(',')
  80. ret = {}
  81. for key, val in items.items():
  82. if key in pickled_keys:
  83. ret[key] = pickle.loads(val)
  84. else:
  85. ret[key] = val
  86. return ret
  87. def download_page(url, data=None):
  88. '''Returns the response for the given url. The optional data argument is
  89. passed directly to urlopen.'''
  90. conn = urllib2.urlopen(url, data)
  91. resp = conn.read()
  92. conn.close()
  93. return resp
  94. _hextochr = dict(('%02x' % i, chr(i)) for i in range(256))
  95. _hextochr.update(('%02X' % i, chr(i)) for i in range(256))
  96. def unhex(inp):
  97. '''unquote(r'abc\x20def') -> 'abc def'.'''
  98. res = inp.split(r'\x')
  99. for i in xrange(1, len(res)):
  100. item = res[i]
  101. try:
  102. res[i] = _hextochr[item[:2]] + item[2:]
  103. except KeyError:
  104. res[i] = '%' + item
  105. except UnicodeDecodeError:
  106. res[i] = unichr(int(item[:2], 16)) + item[2:]
  107. return ''.join(res)