Fix metadata mediabrowser when no actors.

Change metadata usage of indexer api keys.
Change make tvdb_api docs consistent to the attributes for show object.
Change consolidate write_file at helpers.
This commit is contained in:
JackDandy 2018-06-09 12:13:21 +01:00
parent 990755f966
commit 0f6f31a3bf
12 changed files with 204 additions and 220 deletions

View file

@ -1,4 +1,10 @@
### 0.16.15 (2018-06-03 21:24:00 UTC)
### 0.16.16 (2018-06-09 12:13:00 UTC)
* Fix metadata mediabrowser when no actors
* Add 'vp9' and 'av1' to ignore word list
### 0.16.15 (2018-06-03 21:24:00 UTC)
* Change garbage_name regex

View file

@ -398,17 +398,17 @@ class Tvdb:
banners (True/False):
Retrieves the banners for a show. These are accessed
via the _banners key of a Show(), for example:
via the banners key of a Show(), for example:
>> Tvdb(banners=True)['scrubs']['_banners'].keys()
>> Tvdb(banners=True)['scrubs']['banners'].keys()
['fanart', 'poster', 'series', 'season']
actors (True/False):
Retrieves a list of the actors for a show. These are accessed
via the _actors key of a Show(), for example:
via the actors key of a Show(), for example:
>> t = Tvdb(actors=True)
>> t['scrubs']['_actors'][0]['name']
>> t['scrubs']['actors'][0]['name']
u'Zach Braff'
custom_ui (tvdb_ui.BaseUI subclass):
@ -524,7 +524,7 @@ class Tvdb:
self.config['url_actorsInfo'] = '%(base_url)sseries/%%s/actors' % self.config
self.config['url_seriesBanner'] = '%(base_url)sseries/%%s/images/query?keyType=%%s' % self.config
self.config['url_artworkPrefix'] = 'https://thetvdb.com/banners/%s'
self.config['url_artworkPrefix'] = 'https://www.thetvdb.com/banners/%s'
def get_new_token(self):
token = sickbeard.THETVDB_V2_API_TOKEN.get('token', None)
@ -784,10 +784,10 @@ class Tvdb:
k, v = k.lower(), v.lower() if isinstance(v, (str, unicode)) else v
if k == 'filename':
k = 'bannerpath'
banners[btype][btype2][bid]['_bannerpath'] = self.config['url_artworkPrefix'] % v
banners[btype][btype2][bid]['bannerpath'] = self.config['url_artworkPrefix'] % v
elif k == 'thumbnail':
k = 'thumbnailpath'
banners[btype][btype2][bid]['_thumbnailpath'] = self.config['url_artworkPrefix'] % v
banners[btype][btype2][bid]['thumbnailpath'] = self.config['url_artworkPrefix'] % v
elif k == 'keytype':
k = 'bannertype'
banners[btype][btype2][bid][k] = v
@ -803,14 +803,14 @@ class Tvdb:
try:
for n in sorted(actor_list, key=lambda x: x['sortorder']):
a.append({'character': {'id': None,
'name': n.get('role', ''),
'name': n.get('role', '').strip(),
'url': None, # not supported by tvdb
'image': (None, self.config['url_artworkPrefix'] % n.get('image'))
[n.get('image')not in (None, '')],
'image': (None, self.config['url_artworkPrefix'] %
n.get('image'))[any([n.get('image')])],
},
'person': {'id': None, # not supported by tvdb
'name': n.get('name', ''),
'url': '', # not supported by tvdb
'name': n.get('name', '').strip(),
'url': None, # not supported by tvdb
'image': None, # not supported by tvdb
'birthday': None, # not supported by tvdb
'deathday': None, # not supported by tvdb

View file

@ -380,7 +380,7 @@ class TvdbV1:
Retrieves the banners for a show. These are accessed
via the _banners key of a Show(), for example:
>> Tvdb(banners=True)['scrubs']['_banners'].keys()
>> Tvdb(banners=True)['scrubs']['banners'].keys()
['fanart', 'poster', 'series', 'season']
actors (True/False):
@ -388,7 +388,7 @@ class TvdbV1:
via the _actors key of a Show(), for example:
>> t = Tvdb(actors=True)
>> t['scrubs']['_actors'][0]['name']
>> t['scrubs']['actors'][0]['name']
u'Zach Braff'
custom_ui (tvdb_ui.BaseUI subclass):
@ -514,7 +514,7 @@ class TvdbV1:
self.config['url_actorsInfo'] = u'%(base_url)s/api/%(apikey)s/series/%%s/actors.xml' % self.config
self.config['url_seriesBanner'] = u'%(base_url)s/api/%(apikey)s/series/%%s/banners.xml' % self.config
self.config['url_artworkPrefix'] = u'%(base_url)s/banners/%%s' % self.config
self.config['url_artworkPrefix'] = u'https://thetvdb.com/banners/%%s' % self.config
def log(self, msg, log_level=logger.DEBUG):
logger.log('TVDB_API :: %s' % (msg.replace(self.config['apikey'], '<apikey>')), log_level=log_level)
@ -699,7 +699,7 @@ class TvdbV1:
>> t = Tvdb(banners = True)
>> t['scrubs']['_banners'].keys()
['fanart', 'poster', 'series', 'season']
>> t['scrubs']['_banners']['poster']['680x1000']['35308']['_bannerpath']
>> t['scrubs']['_banners']['poster']['680x1000']['35308']['bannerpath']
u'http://thetvdb.com/banners/posters/76156-2.jpg'
>>
@ -751,7 +751,7 @@ class TvdbV1:
Actors are retrieved using t['show name]['_actors'], for example:
>> t = Tvdb(actors = True)
>> actors = t['scrubs']['_actors']
>> actors = t['scrubs']['actors']
>> type(actors)
<class 'tvdb_api.Actors'>
>> type(actors[0])
@ -775,14 +775,14 @@ class TvdbV1:
try:
for n in sorted(actors_et['Actor'], key=lambda x: x['SortOrder']):
a.append({'character': {'id': None,
'name': n.get('Role', ''),
'name': n.get('Role', '').strip(),
'url': None, # not supported by tvdb
'image': (None, self.config['url_artworkPrefix'] % n.get('Image'))
[n.get('Image')not in (None, '')],
'image': (None, self.config['url_artworkPrefix'] %
n.get('Image'))[any([n.get('Image')])],
},
'person': {'id': None, # not supported by tvdb
'name': n.get('Name', ''),
'url': '', # not supported by tvdb
'name': n.get('Name', '').strip(),
'url': None, # not supported by tvdb
'image': None, # not supported by tvdb
'birthday': None, # not supported by tvdb
'deathday': None, # not supported by tvdb

View file

@ -847,20 +847,29 @@ class ConfigMigrator:
sickbeard.CACHE_DIR = cache_default
@staticmethod
def _migrate_v17():
def add_ignore_words(wordlist):
# add words to ignore list and insert spaces to improve the ui config readability
words_to_add = ['vp9', 'av1']
if not isinstance(wordlist, list):
wordlist = [wordlist]
config_words = sickbeard.IGNORE_WORDS.split(',')
new_list = []
for new_word in words_to_add:
using_regex = ''
for new_word in wordlist:
add_word = True
for ignore_word in config_words:
ignored = ignore_word.strip().lower()
if ignored.startswith('regex:'):
ignored = ignored.lstrip('regex:')
using_regex = 'regex:'
if ignored and ignored not in new_list:
new_list += [ignored]
if re.search(r'(?i)%s' % new_word, ignored):
if new_word in ignored:
add_word = False
if add_word:
new_list += [new_word]
sickbeard.IGNORE_WORDS = ', '.join(sorted(new_list))
sickbeard.IGNORE_WORDS = '%s%s' % (using_regex, ', '.join(new_list))
def _migrate_v17(self):
self.add_ignore_words(['vp9', 'av1'])

View file

@ -20,9 +20,11 @@ from __future__ import print_function
from __future__ import with_statement
import base64
import codecs
import datetime
import getpass
import hashlib
import io
import os
import re
import shutil
@ -360,7 +362,7 @@ def moveAndSymlinkFile(srcFile, destFile):
copyFile(srcFile, destFile)
def make_dirs(path):
def make_dirs(path, syno=True):
"""
Creates any folders that are missing and assigns them the permissions of their
parents
@ -394,6 +396,7 @@ def make_dirs(path):
ek.ek(os.mkdir, sofar)
# use normpath to remove end separator, otherwise checks permissions against itself
chmodAsParent(ek.ek(os.path.normpath, sofar))
if syno:
# do the library update for synoindex
notifiers.NotifierFactory().get('SYNOINDEX').addFolder(sofar)
except (OSError, IOError) as e:
@ -1251,17 +1254,8 @@ def getURL(url, post_data=None, params=None, headers=None, timeout=30, session=N
if savename:
try:
with open(savename, 'wb') as fp:
for chunk in response.iter_content(chunk_size=1024):
if chunk:
fp.write(chunk)
fp.flush()
ek.ek(os.fsync, fp.fileno())
chmodAsParent(savename)
except EnvironmentError as e:
logger.log(u'Unable to save the file: ' + ex(e), logger.ERROR)
write_file(savename, response, raw=True, raise_exceptions=raise_exceptions)
except (StandardError, Exception) as e:
if raise_exceptions:
raise e
return
@ -1703,3 +1697,44 @@ def path_mapper(search, replace, subject):
result = os.path.normpath(re.sub(delim, '/', result))
return result, result != subject
def write_file(filepath, data, raw=False, xmltree=False, utf8=False, raise_exceptions=False):
result = False
if make_dirs(ek.ek(os.path.dirname, filepath), False):
try:
if raw:
with io.FileIO(filepath, 'wb') as fh:
for chunk in data.iter_content(chunk_size=1024):
if chunk:
fh.write(chunk)
fh.flush()
ek.ek(os.fsync, fh.fileno())
else:
w_mode = 'w'
if utf8:
w_mode = 'a'
with io.FileIO(filepath, 'wb') as fh:
fh.write(codecs.BOM_UTF8)
if xmltree:
with io.FileIO(filepath, w_mode) as fh:
if utf8:
data.write(fh, encoding='utf-8')
else:
data.write(fh)
else:
with io.FileIO(filepath, w_mode) as fh:
fh.write(data)
chmodAsParent(filepath)
result = True
except (EnvironmentError, IOError) as e:
logger.log('Unable to write file %s : %s' % (filepath, ex(e)), logger.ERROR)
if raise_exceptions:
raise e
return result

View file

@ -320,7 +320,6 @@ class GenericMetadata():
logger.DEBUG)
nfo_file_path = self.get_show_file_path(show_obj)
try:
with ek.ek(open, nfo_file_path, 'r') as xmlFileObj:
show_xml = etree.ElementTree(file=xmlFileObj)
@ -343,13 +342,9 @@ class GenericMetadata():
# Make it purdy
helpers.indentXML(root)
show_xml.write(nfo_file_path)
helpers.chmodAsParent(nfo_file_path)
helpers.write_file(nfo_file_path, show_xml, xmltree=True, utf8=True)
return True
except IOError as e:
logger.log(u'Unable to write file %s - is the folder writable? %s' % (nfo_file_path, ex(e)),
logger.ERROR)
def create_fanart(self, show_obj):
if self.fanart and show_obj and not self._has_fanart(show_obj):
@ -476,27 +471,10 @@ class GenericMetadata():
return False
nfo_file_path = self.get_show_file_path(show_obj)
nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path)
try:
if not ek.ek(os.path.isdir, nfo_file_dir):
logger.log(u"Metadata dir didn't exist, creating it at " + nfo_file_dir, logger.DEBUG)
ek.ek(os.makedirs, nfo_file_dir)
helpers.chmodAsParent(nfo_file_dir)
logger.log(u'Writing show metadata file: %s' % nfo_file_path, logger.DEBUG)
logger.log(u"Writing show nfo file to " + nfo_file_path, logger.DEBUG)
nfo_file = ek.ek(open, nfo_file_path, 'w')
data.write(nfo_file, encoding="utf-8")
nfo_file.close()
helpers.chmodAsParent(nfo_file_path)
except IOError as e:
logger.log(u"Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + ex(e),
logger.ERROR)
return False
return True
return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True)
def write_ep_file(self, ep_obj):
"""
@ -521,27 +499,10 @@ class GenericMetadata():
return False
nfo_file_path = self.get_episode_file_path(ep_obj)
nfo_file_dir = ek.ek(os.path.dirname, nfo_file_path)
try:
if not ek.ek(os.path.isdir, nfo_file_dir):
logger.log(u"Metadata dir didn't exist, creating it at " + nfo_file_dir, logger.DEBUG)
ek.ek(os.makedirs, nfo_file_dir)
helpers.chmodAsParent(nfo_file_dir)
logger.log(u'Writing episode metadata file: %s' % nfo_file_path, logger.DEBUG)
logger.log(u"Writing episode nfo file to " + nfo_file_path, logger.DEBUG)
nfo_file = ek.ek(open, nfo_file_path, 'w')
data.write(nfo_file, encoding="utf-8")
nfo_file.close()
helpers.chmodAsParent(nfo_file_path)
except IOError as e:
logger.log(u"Unable to write file to " + nfo_file_path + " - are you sure the folder is writable? " + ex(e),
logger.ERROR)
return False
return True
return helpers.write_file(nfo_file_path, data, xmltree=True, utf8=True)
def save_thumbnail(self, ep_obj):
"""
@ -911,12 +872,12 @@ class GenericMetadata():
if not self._valid_show(indexer_show_obj, show_obj):
return result
season_images = getattr(indexer_show_obj, '_banners', {}).get(
season_images = getattr(indexer_show_obj, 'banners', {}).get(
('season', 'seasonwide')['seasonwides' == image_type], {}).get(season, {})
for image_id in season_images.keys():
if season not in result:
result[season] = {}
result[season][image_id] = season_images[image_id]['_bannerpath']
result[season][image_id] = season_images[image_id]['bannerpath']
return result

View file

@ -187,24 +187,7 @@ class KODIMetadata(generic.GenericMetadata):
if getattr(myShow, 'network', None) is not None:
studio.text = myShow['network']
if getattr(myShow, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor = etree.SubElement(tv_node, 'actor')
cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
self.add_actor_element(myShow, etree, tv_node)
# Make it purdy
helpers.indentXML(tv_node)
@ -351,24 +334,7 @@ class KODIMetadata(generic.GenericMetadata):
cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name.text = actor
if getattr(myEp, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor = etree.SubElement(episode, 'actor')
cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
self.add_actor_element(myShow, etree, episode)
# Make it purdy
helpers.indentXML(rootNode)
@ -377,6 +343,26 @@ class KODIMetadata(generic.GenericMetadata):
return data
@staticmethod
def add_actor_element(my_show, et, node):
for actor in getattr(my_show, 'actors', []):
cur_actor = et.SubElement(node, 'actor')
cur_actor_name = et.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['person']['name']
if cur_actor_name_text:
cur_actor_name.text = cur_actor_name_text
cur_actor_role = et.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = et.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['character']['image']
if None is not cur_actor_thumb_text:
cur_actor_thumb.text = cur_actor_thumb_text
# present a standard "interface" from the module
metadata_class = KODIMetadata

View file

@ -199,14 +199,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
Runtime.text = myShow['runtime']
cast = etree.SubElement(tv_node, "cast")
if getattr(myShow, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor_name_text = actor['name']
if cur_actor_name_text != None and cur_actor_name_text.strip():
cur_actor = etree.SubElement(cast, "actor")
cur_actor.text = cur_actor_name_text.strip()
self.add_actor_element(myShow, etree, cast)
helpers.indentXML(rootNode)
@ -333,14 +326,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
credits.text = credits_text
cast = etree.SubElement(episode, "cast")
if getattr(myShow, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor_name_text = actor['name']
if cur_actor_name_text != None and cur_actor_name_text.strip():
cur_actor = etree.SubElement(cast, "actor")
cur_actor.text = cur_actor_name_text.strip()
self.add_actor_element(myShow, etree, cast)
else:
# append data from (if any) related episodes
@ -362,6 +348,17 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
return data
@staticmethod
def add_actor_element(my_show, et, node):
for actor in getattr(my_show, 'actors', []):
cur_actor_name_text = actor['character']['name'] and actor['person']['name'] \
and actor['character']['name'] != actor['person']['name'] \
and '%s (%s)' % (actor['character']['name'], actor['person']['name']) \
or actor['person']['name'] or actor['character']['name']
if cur_actor_name_text:
cur_actor = et.SubElement(node, 'actor')
cur_actor.text = cur_actor_name_text
# present a standard "interface" from the module
metadata_class = Mede8erMetadata

View file

@ -362,17 +362,19 @@ class MediaBrowserMetadata(generic.GenericMetadata):
if getattr(myShow, 'network', None) is not None:
Studio.text = myShow['network']
Persons = etree.SubElement(tv_node, "Persons")
if getattr(myShow, 'actors', None) is not None:
for actor in myShow['_actors']:
cur_actor = etree.SubElement(Persons, "Person")
cur_actor_name = etree.SubElement(cur_actor, "Name")
cur_actor_name.text = actor['name'].strip()
cur_actor_type = etree.SubElement(cur_actor, "Type")
cur_actor_type.text = "Actor"
cur_actor_role = etree.SubElement(cur_actor, "Role")
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
Persons = etree.SubElement(tv_node, 'Persons')
for actor in getattr(myShow, 'actors', []):
cur_actor = etree.SubElement(Persons, 'Person')
cur_actor_name = etree.SubElement(cur_actor, 'Name')
cur_actor_name.text = actor['person']['name']
cur_actor_type = etree.SubElement(cur_actor, 'Type')
cur_actor_type.text = 'Actor'
cur_actor_role = etree.SubElement(cur_actor, 'Role')
cur_actor_role_text = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
helpers.indentXML(tv_node)

View file

@ -252,15 +252,16 @@ class TIVOMetadata(generic.GenericMetadata):
# This must be entered as yyyy-mm-ddThh:mm:ssZ (the t is capitalized and never changes, the Z is also
# capitalized and never changes). This is the original air date of the episode.
# NOTE: Hard coded the time to T00:00:00Z as we really don't know when during the day the first run happened.
# NOTE: Hard coded the time to T00:00:00Z as we really don't know when during the day the first run happened
if curEpToWrite.airdate != datetime.date.fromordinal(1):
data += ("originalAirDate : " + str(curEpToWrite.airdate) + "T00:00:00Z\n")
# This shows up at the beginning of the description on the Program screen and on the Details screen.
if getattr(myShow, 'actors', None) is not None:
for actor in myShow["actors"].split('|'):
if actor:
data += ("vActor : " + actor + "\n")
for actor in getattr(myShow, 'actors', []):
data += ('vActor : %s\n' % actor['character']['name'] and actor['person']['name']
and actor['character']['name'] != actor['person']['name']
and '%s (%s)' % (actor['character']['name'], actor['person']['name'])
or actor['person']['name'] or actor['character']['name'])
# This is shown on both the Program screen and the Details screen.
if getattr(myEp, 'rating', None) is not None:

View file

@ -275,14 +275,15 @@ class WDTVMetadata(generic.GenericMetadata):
if director_text is not None:
director.text = director_text
if getattr(myShow, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor = etree.SubElement(episode, "actor")
cur_actor_name = etree.SubElement(cur_actor, "name")
cur_actor_name.text = actor['name']
cur_actor_role = etree.SubElement(cur_actor, "role")
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
for actor in getattr(myShow, 'actors', []):
cur_actor = etree.SubElement(episode, 'actor')
cur_actor_name = etree.SubElement(cur_actor, 'name')
cur_actor_name.text = actor['person']['name']
cur_actor_role = etree.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
overview = etree.SubElement(episode, "overview")

View file

@ -187,24 +187,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
if getattr(myShow, 'network', None) is not None:
studio.text = myShow["network"]
if getattr(myShow, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor = etree.SubElement(tv_node, "actor")
cur_actor_name = etree.SubElement(cur_actor, "name")
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, "role")
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, "thumb")
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
self.add_actor_element(myShow, etree, tv_node)
# Make it purdy
helpers.indentXML(tv_node)
@ -354,24 +337,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
cur_actor_name = etree.SubElement(cur_actor, "name")
cur_actor_name.text = actor
if getattr(myEp, '_actors', None) is not None:
for actor in myShow['_actors']:
cur_actor = etree.SubElement(episode, "actor")
cur_actor_name = etree.SubElement(cur_actor, "name")
cur_actor_name_text = actor['name']
if isinstance(cur_actor_name_text, basestring):
cur_actor_name.text = cur_actor_name_text.strip()
cur_actor_role = etree.SubElement(cur_actor, "role")
cur_actor_role_text = actor['role']
if cur_actor_role_text != None:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = etree.SubElement(cur_actor, "thumb")
cur_actor_thumb_text = actor['image']
if cur_actor_thumb_text != None:
cur_actor_thumb.text = cur_actor_thumb_text
self.add_actor_element(myShow, etree, episode)
# Make it purdy
helpers.indentXML(rootNode)
@ -380,6 +346,26 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
return data
@staticmethod
def add_actor_element(my_show, et, node):
for actor in getattr(my_show, 'actors', []):
cur_actor = et.SubElement(node, 'actor')
cur_actor_name = et.SubElement(cur_actor, 'name')
cur_actor_name_text = actor['person']['name']
if cur_actor_name_text:
cur_actor_name.text = cur_actor_name_text
cur_actor_role = et.SubElement(cur_actor, 'role')
cur_actor_role_text = actor['character']['name']
if cur_actor_role_text:
cur_actor_role.text = cur_actor_role_text
cur_actor_thumb = et.SubElement(cur_actor, 'thumb')
cur_actor_thumb_text = actor['character']['image']
if None is not cur_actor_thumb_text:
cur_actor_thumb.text = cur_actor_thumb_text
# present a standard "interface" from the module
metadata_class = XBMC_12PlusMetadata