def _ep_data(self, ep_obj): """ Creates an elementTree XML structure for a MediaBrowser style episode.xml and returns the resulting data object. show_obj: a TVShow instance to create the NFO for """ eps_to_write = [ep_obj] + ep_obj.relatedEps persons_dict = { 'Director': [], 'GuestStar': [], 'Writer': [] } indexer_lang = ep_obj.show.lang try: lINDEXER_API_PARMS = sickbeard.indexerApi(ep_obj.show.indexer).api_params.copy() lINDEXER_API_PARMS['actors'] = True lINDEXER_API_PARMS['language'] = indexer_lang or sickbeard.INDEXER_DEFAULT_LANGUAGE if ep_obj.show.dvdorder: lINDEXER_API_PARMS['dvdorder'] = True t = sickbeard.indexerApi(ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS) myShow = t[ep_obj.show.indexerid] except sickbeard.indexer_shownotfound as e: raise ShowNotFoundException(e.message) except sickbeard.indexer_error as e: logger.log("Unable to connect to " + sickbeard.indexerApi( ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR) return False rootNode = etree.Element("Item") # write an MediaBrowser XML containing info for all matching episodes for curEpToWrite in eps_to_write: try: myEp = myShow[curEpToWrite.season][curEpToWrite.episode] except (sickbeard.indexer_episodenotfound, sickbeard.indexer_seasonnotfound): logger.log("Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format( curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name)) return None if curEpToWrite == ep_obj: # root (or single) episode # default to today's date for specials if firstaired is not set if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None): myEp['firstaired'] = str(datetime.date.fromordinal(1)) if not (getattr(myEp, 'episodename', None) and getattr(myEp, 'firstaired', None)): return None episode = rootNode if curEpToWrite.name: EpisodeName = etree.SubElement(episode, "EpisodeName") EpisodeName.text = curEpToWrite.name EpisodeNumber = etree.SubElement(episode, "EpisodeNumber") EpisodeNumber.text = str(ep_obj.episode) if ep_obj.relatedEps: EpisodeNumberEnd = etree.SubElement(episode, "EpisodeNumberEnd") EpisodeNumberEnd.text = str(curEpToWrite.episode) SeasonNumber = etree.SubElement(episode, "SeasonNumber") SeasonNumber.text = str(curEpToWrite.season) if not ep_obj.relatedEps and getattr(myEp, 'absolute_number', None): absolute_number = etree.SubElement(episode, "absolute_number") absolute_number.text = str(myEp['absolute_number']) if curEpToWrite.airdate != datetime.date.fromordinal(1): FirstAired = etree.SubElement(episode, "FirstAired") FirstAired.text = str(curEpToWrite.airdate) MetadataType = etree.SubElement(episode, "Type") MetadataType.text = "Episode" if curEpToWrite.description: Overview = etree.SubElement(episode, "Overview") Overview.text = curEpToWrite.description if not ep_obj.relatedEps: if getattr(myEp, 'rating', None): Rating = etree.SubElement(episode, "Rating") Rating.text = myEp['rating'] if getattr(myShow, 'imdb_id', None): IMDB_ID = etree.SubElement(episode, "IMDB_ID") IMDB_ID.text = myShow['imdb_id'] IMDB = etree.SubElement(episode, "IMDB") IMDB.text = myShow['imdb_id'] IMDbId = etree.SubElement(episode, "IMDbId") IMDbId.text = myShow['imdb_id'] indexerid = etree.SubElement(episode, "id") indexerid.text = str(curEpToWrite.indexerid) Persons = etree.SubElement(episode, "Persons") if getattr(myShow, '_actors', None): for actor in myShow['_actors']: if not ('name' in actor and actor['name'].strip()): continue 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" if 'role' in actor and actor['role'].strip(): cur_actor_role = etree.SubElement(cur_actor, "Role") cur_actor_role.text = actor['role'].strip() Language = etree.SubElement(episode, "Language") try: Language.text = myEp['language'] except Exception: Language.text = sickbeard.INDEXER_DEFAULT_LANGUAGE # tvrage api doesn't provide language so we must assume a value here thumb = etree.SubElement(episode, "filename") # TODO: See what this is needed for.. if its still needed # just write this to the NFO regardless of whether it actually exists or not # note: renaming files after nfo generation will break this, tough luck thumb_text = self.get_episode_thumb_path(ep_obj) if thumb_text: thumb.text = thumb_text else: # append data from (if any) related episodes EpisodeNumberEnd.text = str(curEpToWrite.episode) if curEpToWrite.name: if not EpisodeName.text: EpisodeName.text = curEpToWrite.name else: EpisodeName.text = EpisodeName.text + ", " + curEpToWrite.name if curEpToWrite.description: if not Overview.text: Overview.text = curEpToWrite.description else: Overview.text = Overview.text + "\r" + curEpToWrite.description # collect all directors, guest stars and writers if getattr(myEp, 'director', None): persons_dict['Director'] += [x.strip() for x in myEp['director'].split('|') if x.strip()] if getattr(myEp, 'gueststars', None): persons_dict['GuestStar'] += [x.strip() for x in myEp['gueststars'].split('|') if x.strip()] if getattr(myEp, 'writer', None): persons_dict['Writer'] += [x.strip() for x in myEp['writer'].split('|') if x.strip()] # fill in Persons section with collected directors, guest starts and writers for person_type, names in six.iteritems(persons_dict): # remove doubles names = list(set(names)) for cur_name in names: Person = etree.SubElement(Persons, "Person") cur_person_name = etree.SubElement(Person, "Name") cur_person_name.text = cur_name cur_person_type = etree.SubElement(Person, "Type") cur_person_type.text = person_type helpers.indentXML(rootNode) data = etree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): """ Creates a key value structure for a Tivo episode metadata file and returns the resulting data object. ep_obj: a TVEpisode instance to create the metadata file for. Lookup the show in http://thetvdb.com/ using the python library: https://github.com/dbr/indexer_api/ The results are saved in the object myShow. The key values for the tivo metadata file are from: http://pytivo.sourceforge.net/wiki/index.php/Metadata """ data = "" eps_to_write = [ep_obj] + ep_obj.relatedEps indexer_lang = ep_obj.show.lang try: lINDEXER_API_PARMS = sickbeard.indexerApi( ep_obj.show.indexer).api_params.copy() lINDEXER_API_PARMS['actors'] = True lINDEXER_API_PARMS[ 'language'] = indexer_lang or sickbeard.INDEXER_DEFAULT_LANGUAGE if ep_obj.show.dvdorder: lINDEXER_API_PARMS['dvdorder'] = True t = sickbeard.indexerApi( ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS) myShow = t[ep_obj.show.indexerid] except sickbeard.indexer_shownotfound as e: raise ShowNotFoundException(str(e)) except sickbeard.indexer_error as e: logger.log( "Unable to connect to " + sickbeard.indexerApi(ep_obj.show.indexer).name + " while creating meta files - skipping - " + str(e), logger.ERROR) return False for curEpToWrite in eps_to_write: try: myEp = myShow[curEpToWrite.season][curEpToWrite.episode] except (sickbeard.indexer_episodenotfound, sickbeard.indexer_seasonnotfound): logger.log( "Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format( curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name)) return None if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None): myEp["firstaired"] = str(datetime.date.fromordinal(1)) if not (getattr(myEp, 'episodename', None) and getattr(myEp, 'firstaired', None)): return None if getattr(myShow, 'seriesname', None): data += ("title : " + myShow["seriesname"] + "\n") data += ("seriesTitle : " + myShow["seriesname"] + "\n") data += ("episodeTitle : " + curEpToWrite._format_pattern('%Sx%0E %EN') + "\n") # This should be entered for episodic shows and omitted for movies. The standard tivo format is to enter # the season number followed by the episode number for that season. For example, enter 201 for season 2 # episode 01. # This only shows up if you go into the Details from the Program screen. # This seems to disappear once the video is transferred to TiVo. # NOTE: May not be correct format, missing season, but based on description from wiki leaving as is. data += ("episodeNumber : " + str(curEpToWrite.episode) + "\n") # Must be entered as true or false. If true, the year from originalAirDate will be shown in parentheses # after the episode's title and before the description on the Program screen. # FIXME: Hardcode isEpisode to true for now, not sure how to handle movies data += "isEpisode : true\n" # Write the synopsis of the video here # Micrsoft Word's smartquotes can die in a fire. sanitizedDescription = curEpToWrite.description # Replace double curly quotes sanitizedDescription = sanitizedDescription.replace( "\u201c", "\"").replace("\u201d", "\"") # Replace single curly quotes sanitizedDescription = sanitizedDescription.replace( "\u2018", "'").replace("\u2019", "'").replace("\u02BC", "'") data += ("description : " + sanitizedDescription + "\n") # Usually starts with "SH" and followed by 6-8 digits. # Tivo uses zap2it for thier data, so the series id is the zap2it_id. if getattr(myShow, 'zap2it_id', None): data += ("seriesId : " + myShow["zap2it_id"] + "\n") # This is the call sign of the channel the episode was recorded from. if getattr(myShow, 'network', None): data += ("callsign : " + myShow["network"] + "\n") # 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. 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): for actor in myShow["_actors"]: if 'name' in actor and actor['name'].strip(): data += ("vActor : " + actor['name'].strip() + "\n") # This is shown on both the Program screen and the Details screen. if getattr(myEp, 'rating', None): try: rating = float(myEp['rating']) except ValueError: rating = 0.0 # convert 10 to 4 star rating. 4 * rating / 10 # only whole numbers or half numbers work. multiply by 2, round, divide by 2.0 rating = round(8 * rating / 10) / 2.0 data += ("starRating : " + str(rating) + "\n") # This is shown on both the Program screen and the Details screen. # It uses the standard TV rating system of: TV-Y7, TV-Y, TV-G, TV-PG, TV-14, TV-MA and TV-NR. if getattr(myShow, 'contentrating', None): data += ("tvRating : " + str(myShow["contentrating"]) + "\n") # This field can be repeated as many times as necessary or omitted completely. if ep_obj.show.genre: for genre in ep_obj.show.genre.split('|'): if genre: data += ("vProgramGenre : " + str(genre) + "\n") # NOTE: The following are metadata keywords are not used # displayMajorNumber # showingBits # displayMinorNumber # colorCode # vSeriesGenre # vGuestStar, vDirector, vExecProducer, vProducer, vWriter, vHost, vChoreographer # partCount # partIndex return data
def _ep_data(self, ep_obj): """ Creates an elementTree XML structure for an KODI-style episode.nfo and returns the resulting data object. show_obj: a TVEpisode instance to create the NFO for """ eps_to_write = [ep_obj] + ep_obj.relatedEps indexer_lang = ep_obj.show.lang lINDEXER_API_PARMS = sickbeard.indexerApi( ep_obj.show.indexer).api_params.copy() lINDEXER_API_PARMS['actors'] = True lINDEXER_API_PARMS[ 'language'] = indexer_lang or sickbeard.INDEXER_DEFAULT_LANGUAGE if ep_obj.show.dvdorder: lINDEXER_API_PARMS['dvdorder'] = True try: t = sickbeard.indexerApi( ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS) myShow = t[ep_obj.show.indexerid] except sickbeard.indexer_shownotfound as e: raise ShowNotFoundException(e.message) except sickbeard.indexer_error as e: logger.log( "Unable to connect to " + sickbeard.indexerApi(ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR) return if len(eps_to_write) > 1: rootNode = etree.Element("kodimultiepisode") else: rootNode = etree.Element("episodedetails") # write an NFO containing info for all matching episodes for curEpToWrite in eps_to_write: try: myEp = myShow[curEpToWrite.season][curEpToWrite.episode] except (sickbeard.indexer_episodenotfound, sickbeard.indexer_seasonnotfound): logger.log( "Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format( curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name)) return None if not getattr(myEp, 'firstaired', None): myEp["firstaired"] = str(datetime.date.fromordinal(1)) if not getattr(myEp, 'episodename', None): logger.log("Not generating nfo because the ep has no title", logger.DEBUG) return None logger.log( "Creating metadata for episode " + str(ep_obj.season) + "x" + str(ep_obj.episode), logger.DEBUG) if len(eps_to_write) > 1: episode = etree.SubElement(rootNode, "episodedetails") else: episode = rootNode if getattr(myEp, 'episodename', None): title = etree.SubElement(episode, "title") title.text = myEp['episodename'] if getattr(myShow, 'seriesname', None): showtitle = etree.SubElement(episode, "showtitle") showtitle.text = myShow['seriesname'] season = etree.SubElement(episode, "season") season.text = str(curEpToWrite.season) episodenum = etree.SubElement(episode, "episode") episodenum.text = str(curEpToWrite.episode) uniqueid = etree.SubElement(episode, "uniqueid") uniqueid.text = str(curEpToWrite.indexerid) if curEpToWrite.airdate != datetime.date.fromordinal(1): aired = etree.SubElement(episode, "aired") aired.text = str(curEpToWrite.airdate) if getattr(myEp, 'overview', None): plot = etree.SubElement(episode, "plot") plot.text = myEp['overview'] if curEpToWrite.season and getattr(myShow, 'runtime', None): runtime = etree.SubElement(episode, "runtime") runtime.text = myShow["runtime"] if getattr(myEp, 'airsbefore_season', None): displayseason = etree.SubElement(episode, "displayseason") displayseason.text = myEp['airsbefore_season'] if getattr(myEp, 'airsbefore_episode', None): displayepisode = etree.SubElement(episode, "displayepisode") displayepisode.text = myEp['airsbefore_episode'] if getattr(myEp, 'filename', None): thumb = etree.SubElement(episode, "thumb") thumb.text = myEp['filename'].strip() # watched = etree.SubElement(episode, "watched") # watched.text = 'false' if getattr(myEp, 'rating', None): rating = etree.SubElement(episode, "rating") rating.text = myEp['rating'] if getattr(myEp, 'writer', None) and isinstance( myEp['writer'], six.string_types): for writer in self._split_info(myEp['writer']): cur_writer = etree.SubElement(episode, "credits") cur_writer.text = writer if getattr(myEp, 'director', None) and isinstance( myEp['director'], six.string_types): for director in self._split_info(myEp['director']): cur_director = etree.SubElement(episode, "director") cur_director.text = director if getattr(myEp, 'gueststars', None) and isinstance( myEp['gueststars'], six.string_types): for actor in self._split_info(myEp['gueststars']): cur_actor = etree.SubElement(episode, "actor") cur_actor_name = etree.SubElement(cur_actor, "name") cur_actor_name.text = actor if getattr(myShow, '_actors', None): for actor in myShow['_actors']: cur_actor = etree.SubElement(episode, "actor") if 'name' in actor and actor['name'].strip(): cur_actor_name = etree.SubElement(cur_actor, "name") cur_actor_name.text = actor['name'].strip() else: continue if 'role' in actor and actor['role'].strip(): cur_actor_role = etree.SubElement(cur_actor, "role") cur_actor_role.text = actor['role'].strip() if 'image' in actor and actor['image'].strip(): cur_actor_thumb = etree.SubElement(cur_actor, "thumb") cur_actor_thumb.text = actor['image'].strip() # Make it purdy helpers.indentXML(rootNode) data = etree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): """ Creates an elementTree XML structure for a MediaBrowser style episode.xml and returns the resulting data object. show_obj: a TVShow instance to create the NFO for """ eps_to_write = [ep_obj] + ep_obj.relatedEps indexer_lang = ep_obj.show.lang try: # There's gotta be a better way of doing this but we don't wanna # change the language value elsewhere lINDEXER_API_PARMS = sickbeard.indexerApi( ep_obj.show.indexer).api_params.copy() lINDEXER_API_PARMS[ 'language'] = indexer_lang or sickbeard.INDEXER_DEFAULT_LANGUAGE if ep_obj.show.dvdorder: lINDEXER_API_PARMS['dvdorder'] = True t = sickbeard.indexerApi( ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS) myShow = t[ep_obj.show.indexerid] except sickbeard.indexer_shownotfound as e: raise ShowNotFoundException(e.message) except sickbeard.indexer_error as e: logger.log( "Unable to connect to TVDB while creating meta files - skipping - " + ex(e), logger.ERROR) return False rootNode = etree.Element("details") movie = etree.SubElement(rootNode, "movie") movie.attrib["isExtra"] = "false" movie.attrib["isSet"] = "false" movie.attrib["isTV"] = "true" # write an MediaBrowser XML containing info for all matching episodes for curEpToWrite in eps_to_write: try: myEp = myShow[curEpToWrite.season][curEpToWrite.episode] except (sickbeard.indexer_episodenotfound, sickbeard.indexer_seasonnotfound): logger.log( "Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format( curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name)) return None if curEpToWrite == ep_obj: # root (or single) episode # default to today's date for specials if firstaired is not set if curEpToWrite.season == 0 and not getattr( myEp, 'firstaired', None): myEp['firstaired'] = str(datetime.date.fromordinal(1)) if not (getattr(myEp, 'episodename', None) and getattr(myEp, 'firstaired', None)): return None episode = movie if curEpToWrite.name: EpisodeName = etree.SubElement(episode, "title") EpisodeName.text = curEpToWrite.name SeasonNumber = etree.SubElement(episode, "season") SeasonNumber.text = str(curEpToWrite.season) EpisodeNumber = etree.SubElement(episode, "episode") EpisodeNumber.text = str(curEpToWrite.episode) if getattr(myShow, "firstaired", None): try: year_text = str( datetime.datetime.strptime(myShow["firstaired"], dateFormat).year) if year_text: year = etree.SubElement(episode, "year") year.text = year_text except Exception: pass if getattr(myShow, "overview", None): plot = etree.SubElement(episode, "plot") plot.text = myShow["overview"] if curEpToWrite.description: Overview = etree.SubElement(episode, "episodeplot") Overview.text = curEpToWrite.description if getattr(myShow, 'contentrating', None): mpaa = etree.SubElement(episode, "mpaa") mpaa.text = myShow["contentrating"] if not ep_obj.relatedEps and getattr(myEp, "rating", None): try: rating = int((float(myEp['rating']) * 10)) except ValueError: rating = 0 if rating: Rating = etree.SubElement(episode, "rating") Rating.text = str(rating) if getattr(myEp, 'director', None): director = etree.SubElement(episode, "director") director.text = myEp['director'] if getattr(myEp, 'writer', None): writer = etree.SubElement(episode, "credits") writer.text = myEp['writer'] if getattr(myShow, '_actors', None) or getattr( myEp, 'gueststars', None): cast = etree.SubElement(episode, "cast") if getattr(myEp, 'gueststars', None) and isinstance( myEp['gueststars'], six.string_types): for actor in (x.strip() for x in myEp['gueststars'].split('|') if x.strip()): cur_actor = etree.SubElement(cast, "actor") cur_actor.text = actor if getattr(myShow, '_actors', None): for actor in myShow['_actors']: if 'name' in actor and actor['name'].strip(): cur_actor = etree.SubElement(cast, "actor") cur_actor.text = actor['name'].strip() else: # append data from (if any) related episodes if curEpToWrite.name: if not EpisodeName.text: EpisodeName.text = curEpToWrite.name else: EpisodeName.text = EpisodeName.text + ", " + curEpToWrite.name if curEpToWrite.description: if not Overview.text: Overview.text = curEpToWrite.description else: Overview.text = Overview.text + "\r" + curEpToWrite.description helpers.indentXML(rootNode) data = etree.ElementTree(rootNode) return data
def _ep_data(self, ep_obj): """ Creates an elementTree XML structure for a WDTV style episode.xml and returns the resulting data object. ep_obj: a TVShow instance to create the NFO for """ eps_to_write = [ep_obj] + ep_obj.relatedEps indexer_lang = ep_obj.show.lang try: lINDEXER_API_PARMS = sickbeard.indexerApi( ep_obj.show.indexer).api_params.copy() lINDEXER_API_PARMS['actors'] = True lINDEXER_API_PARMS[ 'language'] = indexer_lang or sickbeard.INDEXER_DEFAULT_LANGUAGE if ep_obj.show.dvdorder: lINDEXER_API_PARMS['dvdorder'] = True t = sickbeard.indexerApi( ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS) myShow = t[ep_obj.show.indexerid] except sickbeard.indexer_shownotfound as e: raise ShowNotFoundException(e.message) except sickbeard.indexer_error as e: logger.log( "Unable to connect to " + sickbeard.indexerApi(ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR) return False rootNode = etree.Element("details") # write an WDTV XML containing info for all matching episodes for curEpToWrite in eps_to_write: try: myEp = myShow[curEpToWrite.season][curEpToWrite.episode] except (sickbeard.indexer_episodenotfound, sickbeard.indexer_seasonnotfound): logger.log( "Metadata writer is unable to find episode {0:d}x{1:d} of {2} on {3}..." "has it been removed? Should I delete from db?".format( curEpToWrite.season, curEpToWrite.episode, curEpToWrite.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name)) return None if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None): myEp["firstaired"] = str(datetime.date.fromordinal(1)) if not (getattr(myEp, 'episodename', None) and getattr(myEp, 'firstaired', None)): return None if len(eps_to_write) > 1: episode = etree.SubElement(rootNode, "details") else: episode = rootNode # TODO: get right EpisodeID episodeID = etree.SubElement(episode, "id") episodeID.text = str(curEpToWrite.indexerid) title = etree.SubElement(episode, "title") title.text = ep_obj.pretty_name() if getattr(myShow, 'seriesname', None): seriesName = etree.SubElement(episode, "series_name") seriesName.text = myShow["seriesname"] if curEpToWrite.name: episodeName = etree.SubElement(episode, "episode_name") episodeName.text = curEpToWrite.name seasonNumber = etree.SubElement(episode, "season_number") seasonNumber.text = str(curEpToWrite.season) episodeNum = etree.SubElement(episode, "episode_number") episodeNum.text = str(curEpToWrite.episode) firstAired = etree.SubElement(episode, "firstaired") if curEpToWrite.airdate != datetime.date.fromordinal(1): firstAired.text = str(curEpToWrite.airdate) if getattr(myShow, 'firstaired', None): try: year_text = str( datetime.datetime.strptime(myShow["firstaired"], dateFormat).year) if year_text: year = etree.SubElement(episode, "year") year.text = year_text except Exception: pass if curEpToWrite.season != 0 and getattr(myShow, 'runtime', None): runtime = etree.SubElement(episode, "runtime") runtime.text = myShow["runtime"] if getattr(myShow, 'genre', None): genre = etree.SubElement(episode, "genre") genre.text = " / ".join([ x.strip() for x in myShow["genre"].split('|') if x.strip() ]) if getattr(myEp, 'director', None): director = etree.SubElement(episode, "director") director.text = myEp['director'] if getattr(myShow, '_actors', None): for actor in myShow['_actors']: if not ('name' in actor and actor['name'].strip()): continue cur_actor = etree.SubElement(episode, "actor") cur_actor_name = etree.SubElement(cur_actor, "name") cur_actor_name.text = actor['name'] if 'role' in actor and actor['role'].strip(): cur_actor_role = etree.SubElement(cur_actor, "role") cur_actor_role.text = actor['role'].strip() if curEpToWrite.description: overview = etree.SubElement(episode, "overview") overview.text = curEpToWrite.description # Make it purdy helpers.indentXML(rootNode) data = etree.ElementTree(rootNode) return data