Example #1
0
    def get_episodes(self, imdb_series):
        # Get more information about the series
        self.ia.update(imdb_series)

        # Get informaon about the episodes
        self.ia.update(imdb_series, 'episodes')

        seasons = imdb_series.get('episodes')
        
        try:
            numberofepisodes = imdb_series.get('number of episodes') - 1
        except TypeError:
            raise DownloadError

        # Import helpers form imdb to sort episodes
        from imdb import helpers

        # Sort Episodes
        helpers.sortedEpisodes(seasons)

        # Ratings
        self.ia.update(imdb_series, 'episodes rating')
        ratings = imdb_series.get('episodes rating')

        counter = 0
        for seasonnumber in seasons.iterkeys():
            if type(seasonnumber) == type(1):
                for imdb_episode_number in seasons[seasonnumber]:  
                    imdb_episode = seasons[seasonnumber][imdb_episode_number]
                    counter += 1
                    yield self.__imdb_episode_to_episode(imdb_episode, imdb_series = imdb_series, ratings = ratings, counter = counter), numberofepisodes
Example #2
0
def get_ep_id_list(imdb_handler, movie):
    """
    Returns a list of episode IDs for a given movie object.
    """
    imdb_handler.update(movie, 'episodes')
    eps = []
    for i in helpers.sortedSeasons(movie):
        for ep in helpers.sortedEpisodes(movie, i):
            eps.append(ep.movieID)
    return eps
Example #3
0
def get_ep_id_list(imdb_handler, movie):
    """
    Returns a list of episode IDs for a given movie object.
    """
    imdb_handler.update(movie, 'episodes')
    eps = []
    for i in helpers.sortedSeasons(movie):
        for ep in helpers.sortedEpisodes(movie, i):
            eps.append(ep.movieID)
    return eps
Example #4
0
    def post(self, id, title):
        typde_name = 'Show'

        import logging

        from imdb import IMDb
        from imdb.helpers import sortedSeasons, sortedEpisodes

        def parse_date(d):
            try:
                return datetime.strptime(d.replace('.', ''), '%d %b %Y')

            except Exception:
                return datetime.strptime(d.replace('.', ''), '%b %Y')

        i = IMDb()
        m = i.get_movie(id)
        i.update(m, 'episodes')

        t = models.Typde.get_by_id(typde_name)

        show = models.Tilde(id=str(m.get('title', title)), label=t.key)
        show.start = parse_date(m['episodes'][1][1]['original air date'])
        show.put()
        
        seasons = sortedSeasons(m)

        for s in seasons:
            if s > 0:
                episodes = sortedEpisodes(m, season=s)

                start_date = parse_date(episodes[0]['original air date'])

                season = models.Tilde(ancestor=show.key)
                season.start = start_date
                season.tag = str(s)
                season.put()

                for (e, i) in zip(episodes, range(1, 100)):
                    start_date = parse_date(e['original air date'])
                    end_date = start_date + timedelta(days=1)

                    episode = models.Tilde(ancestor=season.key)
                    episode.start = start_date
                    episode.end = end_date
                    episode.tag = str(i)
                    episode.title = e['title']
                    episode.put()

                season.end = end_date
                season.put()

        show.end = end_date
        show.put()
Example #5
0
def get_ep_from_movie(imdb_handler, movie):
    """
    Original function that'll probably get removed or repurposed.
    Don't worry about this for now.

    ['_Container__role', '__class__', '__cmp__', '__contains__', '__deepcopy__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__len__', '__module__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', '_additional_keys', '_clear', '_get_currentRole', '_get_roleID', '_getitem', '_init', '_re_fullsizeURL', '_reset', '_roleClass', '_roleIsPerson', '_set_currentRole', '_set_roleID', 'accessSystem', 'add_to_current_info', 'append_item', 'asXML', 'charactersRefs', 'clear', 'cmpFunct', 'copy', 'currentRole', 'current_info', 'data', 'default_info', 'get', 'getAsXML', 'getID', 'get_charactersRefs', 'get_current_info', 'get_namesRefs', 'get_titlesRefs', 'guessLanguage', 'has_current_info', 'has_key', 'infoset2keys', 'isSame', 'isSameMovie', 'isSameTitle', 'items', 'iteritems', 'iterkeys', 'itervalues', 'key2infoset', 'keys', 'keys_alias', 'keys_tomodify', 'keys_tomodify_list', 'modFunct', 'movieID', 'myID', 'myTitle', 'namesRefs', 'notes', 'pop', 'popitem', 'reset', 'roleID', 'set_current_info', 'set_data', 'set_item', 'set_mod_funct', 'set_title', 'setdefault', 'smartCanonicalTitle', 'summary', 'titlesRefs', 'update', 'update_charactersRefs', 'update_infoset_map', 'update_namesRefs', 'update_titlesRefs', 'values']

    {'episode': 16,
     'episode of': <Movie id:0903747[http] title:_"Breaking Bad (TV Series 2008–2013)" (????)_>,
     'kind': u'episode',
     'original air date': u'29 Sep. 2013',
     'plot': u'\nWalt ties up whatever loose ends are left as the end draws near.    ',
     'season': 5,
     'title': u'Felina',
     'year': u'2013'}
    """
    imdb_handler.update(movie, 'episodes')
    for i in helpers.sortedSeasons(movie):
        print '\nSEASON ' + str(i) + ':'
        for ep in helpers.sortedEpisodes(movie, i):
            print ep['title']
Example #6
0
def get_ep_from_movie(imdb_handler, movie):
    """
    Original function that'll probably get removed or repurposed.
    Don't worry about this for now.

    ['_Container__role', '__class__', '__cmp__', '__contains__', '__deepcopy__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__len__', '__module__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', '_additional_keys', '_clear', '_get_currentRole', '_get_roleID', '_getitem', '_init', '_re_fullsizeURL', '_reset', '_roleClass', '_roleIsPerson', '_set_currentRole', '_set_roleID', 'accessSystem', 'add_to_current_info', 'append_item', 'asXML', 'charactersRefs', 'clear', 'cmpFunct', 'copy', 'currentRole', 'current_info', 'data', 'default_info', 'get', 'getAsXML', 'getID', 'get_charactersRefs', 'get_current_info', 'get_namesRefs', 'get_titlesRefs', 'guessLanguage', 'has_current_info', 'has_key', 'infoset2keys', 'isSame', 'isSameMovie', 'isSameTitle', 'items', 'iteritems', 'iterkeys', 'itervalues', 'key2infoset', 'keys', 'keys_alias', 'keys_tomodify', 'keys_tomodify_list', 'modFunct', 'movieID', 'myID', 'myTitle', 'namesRefs', 'notes', 'pop', 'popitem', 'reset', 'roleID', 'set_current_info', 'set_data', 'set_item', 'set_mod_funct', 'set_title', 'setdefault', 'smartCanonicalTitle', 'summary', 'titlesRefs', 'update', 'update_charactersRefs', 'update_infoset_map', 'update_namesRefs', 'update_titlesRefs', 'values']

    {'episode': 16,
     'episode of': <Movie id:0903747[http] title:_"Breaking Bad (TV Series 2008–2013)" (????)_>,
     'kind': u'episode',
     'original air date': u'29 Sep. 2013',
     'plot': u'\nWalt ties up whatever loose ends are left as the end draws near.    ',
     'season': 5,
     'title': u'Felina',
     'year': u'2013'}
    """
    imdb_handler.update(movie, 'episodes')
    for i in helpers.sortedSeasons(movie):
        print '\nSEASON ' + str(i) + ':'
        for ep in helpers.sortedEpisodes(movie, i):
            print ep['title']
Example #7
0
def getEps(title, max_len=990, debug=False):  # 1024-32-2 = 990
    """Returns a text string containing schedule info for the last aired and the next upcoming episodes for the given TV series title"""

    # Validate title
    assert isinstance(title, str), 'A string input was not provided.'

    # Preprocess title
    title = title.strip()

    # Determine if the next upcoming episode's plot should be included if available (Default is True)
    if title.lower().endswith('/noplot'):
        title = title[:-len('/noplot')].rstrip()
        include_plot = False
    else:
        include_plot = True

    try:

        # Validate title further
        if len(title) == 0: return 'A title was not provided.'

        # Create IMDb object
        i = IMDb()

        # Get search results
        max_attempts = 3  # Set to anything greater than 1
        for attempt in range(1, max_attempts + 1):
            try:
                search_results = i.search_movie(title)
                break
            except:
                if attempt < max_attempts:
                    if debug:
                        print 'An error occurred while attempting to retrieve search results for "%s". %s attempts were made.' % (
                            title, attempt) + '\n'
                    sleep(attempt * 2)
                else:
                    return 'An error occurred while attempting to retrieve search results for "%s". %s attempts were made.' % (
                        title, attempt)
        del attempt, max_attempts

        # Get first search result that is a TV series
        search_results = ifilter(lambda s: s['kind'] == 'tv series',
                                 search_results)
        search_results = list(islice(search_results, 0, 1))
        if len(search_results) == 0:
            return 'No TV series matches were found for "%s".' % title
        s = search_results[0]
        del search_results

        # Get episodes
        i.update(s, 'episodes')
        s_title = s['long imdb title']
        if (not s.has_key('episodes')) or len(s['episodes']) == 0:
            return 'Episode info is unavailable for %s.' % s_title
        s = sortedEpisodes(s)
        if len(s) == 0: return 'Episode info is unavailable for %s.' % s_title

        # Sort episodes in approximately the desired order
        s.reverse(
        )  # This results in episodes that are sorted in the desired order. If, however, the episodes are not listed in proper order at the source, such as for "Showtime Championship Boxing" (1987) as of 2/29/08, the error will be copied here.
        s = list(dropwhile(lambda e: e['season'] == 'unknown', s)) + list(
            takewhile(lambda e: e['season'] == 'unknown', s)
        )  # While this may not always produce the most accurate results, it prevents episodes belonging to an unknown season from being thought of as most recent.

        # Process date related info for episodes
        date_today = date.today()
        for ep_ind in xrange(len(s)):
            if s[ep_ind].has_key('original air date'):
                try:
                    s[ep_ind]['date'] = strptime(
                        s[ep_ind]['original air date'], '%d %B %Y')
                except:
                    pass
            if s[ep_ind].has_key('date'):
                s[ep_ind]['date'] = date(*s[ep_ind]['date'][0:3])
                s[ep_ind]['age'] = (
                    s[ep_ind]['date'] -
                    date_today).days  # Age is date delta in days
                if s[ep_ind]['age'] < 0:
                    s[ep_ind]['has aired'] = True
                else:
                    s[ep_ind]['has aired'] = False
            else:
                s[ep_ind]['has aired'] = False
        del date_today, ep_ind

        # Print last 10 listed episodes (if debugging)
        if debug:
            print 'Last 10 listed episodes:\nS# Epi# Age   Episode Title'
            for e in s[:10]:
                print '%s %s %s %s' % (
                    str(e['season']).zfill(2)[:2], str(e['episode']).zfill(4),
                    e.has_key('age') and str(e['age']).zfill(5)
                    or ' ' * 5, e['title'].encode('latin-1'))
            print

        # Declare convenient functions for use in generating output string
        def getSE(e):
            if not isinstance(e['season'], int): return ''
            Sstr = 'S' + str(e['season']).zfill(2)
            Estr = 'E' + str(e['episode']).zfill(2)
            return ' (' + Sstr + Estr + ')'

        def getAge(e):
            return locale.format('%i', abs(e['age']), grouping=True)

        def getDate(e):
            return 'i.e. on ' + e['date'].strftime('%a, ') + str(
                e['date'].day) + e['date'].strftime(' %b %y')

        # Determine last aired episode
        # (An episode that airs today is considered to be not yet aired)
        e = ifilter(lambda e: e['has aired'], s)
        e = list(islice(e, 0, 1))
        if len(e) > 0:
            e = e[0]
            e_schedule = e['age'] != -1 and ('%s days ago' %
                                             getAge(e)) or 'yesterday'

            # Generate output string when last aired episode is available
            e_out = 'The episode that aired last for ' + s_title + ' is "' + e[
                'title'] + '"' + getSE(
                    e) + '. It aired ' + e_schedule + ', ' + getDate(e) + '. '
            del e_schedule

        else:
            # Generate output string when last aired episode is unavailable
            e_out = ''

        # Determine next upcoming episode
        # (An episode that airs today is considered to be an upcoming episode)
        e = list(takewhile(lambda e: e['has aired'] == False,
                           s))  # Memory inefficient
        if len(e) > 0:
            e = e[-1]

            # Generate output string when next upcoming episode is available
            e_out = e_out + 'The next upcoming episode ' + (
                e_out == '' and ('for ' + s_title + ' ')
                or '') + 'is "' + e['title'] + '"' + getSE(e) + '.'

            if e.has_key('age'):
                e_schedule = e['age'] > 1 and (
                    'in %s days' % getAge(e)
                ) or e['age'] == 1 and 'tomorrow' or e['age'] == 0 and 'today'
                e_out = e_out + ' It airs ' + e_schedule + ', ' + getDate(
                    e) + '.'
                del e_schedule
            else:
                e_out = e_out + ' Its air date is unavailable.'

            if include_plot:
                if e.has_key('plot') and e['plot'] != 'Related Links':
                    e_out = e_out + ' Its plot is: ' + e['plot']
                elif e_out.endswith('Its air date is unavailable.'):
                    e_out = e_out.replace(
                        'Its air date is unavailable.',
                        'Its air date and plot are unavailable.')
                else:
                    e_out = e_out + ' Its plot is unavailable.'

        else:
            if e_out != '':  # Last: available; Next: unavailable
                e_out = e_out + 'No upcoming episode is scheduled.'
            else:  # Last: unavailable; Next: unavailable
                e_out = 'Episode info is unavailable for %s.' % s_title

        # Conditionally trim output string
        if (max_len not in [-1, 0, None]) and len(e_out) > max_len - 3:
            e_out = e_out[:max_len - 3] + '...'

        # Return output string
        return e_out

    except:
        return 'An error occurred while attempting to retrieve episode info for "%s".' % title
Example #8
0
def add_to_db(series_list_file, create_tables):
    conn, session = create_connection(eval(create_tables))
    ia = IMDb()
    with open(series_list_file) as f:
        for ser in f:
            print(f'Extracting IMDB data for: {ser}')
            s = ia.get_movie(ser)
            print(f'IMDB data loaded for {s}')

            # Make sure the series has been loaded already
            quer = session.query(Series).filter(
                Series.tconst == s.getID()).all()
            if len(quer) != 1:
                print(
                    f'Series {s} not found in database. Load this before adding episodes.'
                )
                break

            # Get the episode data through IMDBpy
            print(f'Extracting IMDB episode data for {s}')
            ia.update(s, 'episodes')
            print(f'IMDB episode data loaded for {s}')

            parent_id = quer[0].id
            parent_tconst = quer[0].tconst

            # Sort episodes using sorted Episodes function from IMDbPY
            episodes = helpers.sortedEpisodes(s)

            for e in episodes:
                print(f'Processing episode: {e}')
                result = Episode()
                result.parent_id = parent_id
                result.parent_tconst = parent_tconst
                try:
                    result.tconst = e.getID()
                except:
                    print(f'tconst not found for {e}')
                    break
                try:
                    if len(e['original air date']) < 5:
                        result.original_air_date = None
                    else:
                        result.original_air_date = parser.parse(
                            e['original air date'])
                except KeyError:
                    result.original_air_date = None
                try:
                    result.number_votes = e['votes']
                except KeyError:
                    result.number_votes = None
                try:
                    result.avg_rating = e['rating']
                except KeyError:
                    result.avg_rating = None
                try:
                    result.season = e['season']
                except KeyError:
                    result.season = None
                try:
                    result.episode = e['episode']
                except KeyError:
                    result.episode = None
                try:
                    result.title = e['title']
                except KeyError:
                    result.title = None
                try:
                    result.plot = e['plot']
                except KeyError:
                    result.plot = None

                print("Commit to Database!!!!!!!")
                session.add(result)
                session.commit()

    conn.close()
Example #9
0
def getEps(title):
    #strip title input by user
    title = title.strip()
    # Create IMDb object
    i = IMDb()
    #search for title
    search_results = i.search_movie(title)
    # Get first search result that is a TV series
    search_results = filter(lambda s: s['kind'] == 'tv series', search_results)
    search_results = list(islice(search_results, 0, 1))
    #if no result found
    if len(search_results) == 0:
        return 'No TV series matches were found for "%s".' % title
    s = search_results[0]
    i.update(s, 'episodes')
    s_title = s['long imdb title']
    #if no episode info found
    if (not s.has_key('episodes')) or len(s['episodes']) == 0:
        return 'Episode info is unavailable for %s.' % s_title
    s = sortedEpisodes(s)
    if len(s) == 0:
        return 'Episode info is unavailable for %s.' % s_title
    s.reverse()
    date_today = date.today()
    e = []
    for ep_ind in range(0, len(s)):
        if s[ep_ind].has_key('original air date'):
            if (len(s[ep_ind]['original air date'])) == 4:
                s[ep_ind]['date'] = strptime(s[ep_ind]['original air date'],
                                             '%Y')
            else:
                s[ep_ind]['date'] = strptime(
                    s[ep_ind]['original air date'].replace('.', ''),
                    '%d %b %Y')
        if s[ep_ind].has_key('date'):
            s[ep_ind]['date'] = date(*s[ep_ind]['date'][0:3])
            s[ep_ind]['age'] = (date_today - s[ep_ind]['date']).days
            if s[ep_ind]['age'] > 0:
                s[ep_ind]['has aired'] = True
            else:
                s[ep_ind]['has aired'] = False
                e.append(s[ep_ind])
        else:
            s[ep_ind]['has aired'] = False
            e.append(s[ep_ind])
    #function to get season episode format for description
    def getSE(e):
        if not isinstance(e['season'], int):
            return ''
        Sstr = 'S' + str(e['season']).zfill(2)
        Estr = 'E' + str(e['episode']).zfill(2)
        return ' (' + Sstr + Estr + ')'

    #function to get age of episode (negative if has not aired, positive if has aired)
    def getAge(e):
        return locale.format('%i', abs(e['age']), grouping=True)

    #function to get date of episode
    def getDate(e):
        return e['date'].strftime('%a, ') + str(
            e['date'].day) + e['date'].strftime(' %b %y')

    titles = []
    descriptions = []
    dates = []
    for i in e:
        e_out = ''
        if len(e) > 0:
            e = i
            titles.append(s_title)
            descriptions.append(getSE(e))
            e_out = e_out + 'The next upcoming episode ' + 'for ' + s_title + ' ' + 'is "' + e[
                'title'] + '"' + getSE(e) + '.'
            if e.has_key('age'):
                e_schedule = 'in %s days' % getAge(e)
                e_out = e_out + ' It airs ' + e_schedule + ', ' + getDate(
                    e) + '.'
                dates.append(getDate(e))
            else:
                e_out = e_out + ' Its air date is unavailable.'
                dates.append('unknown')
        print(e_out)
    return titles, descriptions, dates
total_plot = []
total_date = []
for t in curr_titles:

    # Create object of all series
    series = ia.get_movie(t)

    #print out listed keys in object
    print(f"Gathering info: {t}")

    # Append Episode Data
    ia.update(series, 'episodes')
    print(f"Appending Episodes to {t}")

    # Sort episodes using sorted Episodes function from IMDbPY
    episodes = helpers.sortedEpisodes(series)
    print(f"Sorting Episodes for {t}")
    print(f">>>>>>>>>>> {episodes[1]['series title']}<<<<<<<<<<<<")
    
    # Create Empty column list variables. 
    title = []
    episode_of = []
    season = []
    episode = []
    rating = []
    votes = []
    original_air_date = []
    year = []
    plot = []
    series_title = []
    episode_title = []
Example #11
0
def getEps(title,max_len=990,debug=False): # 1024-32-2 = 990
	"""Returns a text string containing schedule info for the last aired and the next upcoming episodes for the given TV series title"""

	# Validate title
	assert isinstance(title,str), 'A string input was not provided.'

	# Preprocess title
	title=title.strip()

	# Determine if the next upcoming episode's plot should be included if available (Default is True)
	if title.lower().endswith('/noplot'):
		title=title[:-len('/noplot')].rstrip()
		include_plot=False
	else:
		include_plot=True

	try:

		# Validate title further
		if len(title)==0: return 'A title was not provided.'
	
		# Create IMDb object
		i=IMDb()
	
		# Get search results
		max_attempts=3 # Set to anything greater than 1
		for attempt in range(1,max_attempts+1):
			try:
				search_results=i.search_movie(title)
				break
			except:
				if attempt<max_attempts:
					if debug: print 'An error occurred while attempting to retrieve search results for "%s". %s attempts were made.'%(title,attempt)+'\n'
					sleep(attempt*2)
				else:
					return 'An error occurred while attempting to retrieve search results for "%s". %s attempts were made.'%(title,attempt)
		del attempt,max_attempts
	
		# Get first search result that is a TV series
		search_results=ifilter(lambda s:s['kind']=='tv series',search_results)
		search_results=list(islice(search_results,0,1))
		if len(search_results)==0: return 'No TV series matches were found for "%s".'%title
		s=search_results[0]
		del search_results
	
		# Get episodes
		i.update(s,'episodes')
		s_title=s['long imdb title']
		if (not s.has_key('episodes')) or len(s['episodes'])==0: return 'Episode info is unavailable for %s.'%s_title
		s=sortedEpisodes(s)
		if len(s)==0: return 'Episode info is unavailable for %s.'%s_title
	
		# Sort episodes in approximately the desired order
		s.reverse() # This results in episodes that are sorted in the desired order. If, however, the episodes are not listed in proper order at the source, such as for "Showtime Championship Boxing" (1987) as of 2/29/08, the error will be copied here.
		s=list(dropwhile(lambda e:e['season']=='unknown',s))+list(takewhile(lambda e:e['season']=='unknown',s)) # While this may not always produce the most accurate results, it prevents episodes belonging to an unknown season from being thought of as most recent.
	
		# Process date related info for episodes
		date_today=date.today()
		for ep_ind in xrange(len(s)):
			if s[ep_ind].has_key('original air date'):
				try:
					s[ep_ind]['date']=strptime(s[ep_ind]['original air date'],'%d %B %Y')
				except:	pass
			if s[ep_ind].has_key('date'):
				s[ep_ind]['date']=date(*s[ep_ind]['date'][0:3])
				s[ep_ind]['age']=(s[ep_ind]['date']-date_today).days # Age is date delta in days
				if s[ep_ind]['age']<0:
					s[ep_ind]['has aired']=True
				else:
					s[ep_ind]['has aired']=False
			else:
				s[ep_ind]['has aired']=False
		del date_today,ep_ind
	
		# Print last 10 listed episodes (if debugging)
		if debug:
			print 'Last 10 listed episodes:\nS# Epi# Age   Episode Title'
			for e in s[:10]: print '%s %s %s %s'%(str(e['season']).zfill(2)[:2],str(e['episode']).zfill(4),e.has_key('age') and str(e['age']).zfill(5) or ' '*5,e['title'].encode('latin-1'))
			print
	
		# Declare convenient functions for use in generating output string
		def getSE(e):
			if not isinstance(e['season'],int): return ''
			Sstr='S'+str(e['season']).zfill(2)
			Estr='E'+str(e['episode']).zfill(2)
			return ' ('+Sstr+Estr+')'
		def getAge(e): return locale.format('%i',abs(e['age']),grouping=True)
		def getDate(e): return 'i.e. on '+e['date'].strftime('%a, ')+str(e['date'].day)+e['date'].strftime(' %b %y')
	
		# Determine last aired episode
		# (An episode that airs today is considered to be not yet aired)
		e=ifilter(lambda e:e['has aired'],s)
		e=list(islice(e,0,1))
		if len(e)>0:
			e=e[0]
			e_schedule= e['age']!=-1 and ('%s days ago'%getAge(e)) or 'yesterday'
	
			# Generate output string when last aired episode is available
			e_out='The episode that aired last for '+s_title+' is "'+e['title']+'"'+getSE(e)+'. It aired '+e_schedule+', '+getDate(e)+'. '
			del e_schedule
	
		else:
			# Generate output string when last aired episode is unavailable
			e_out=''
	
		# Determine next upcoming episode
		# (An episode that airs today is considered to be an upcoming episode)
		e=list(takewhile(lambda e:e['has aired']==False,s)) # Memory inefficient
		if len(e)>0:
			e=e[-1]
	
			# Generate output string when next upcoming episode is available
			e_out=e_out+'The next upcoming episode '+(e_out=='' and ('for '+s_title+' ') or '')+'is "'+e['title']+'"'+getSE(e)+'.'
	
			if e.has_key('age'):
				e_schedule= e['age']>1 and ('in %s days'%getAge(e)) or e['age']==1 and 'tomorrow' or e['age']==0 and 'today'
				e_out=e_out+' It airs '+e_schedule+', '+getDate(e)+'.'
				del e_schedule
			else:
				e_out=e_out+' Its air date is unavailable.'
	
			if include_plot:
				if e.has_key('plot') and e['plot']!='Related Links':
					e_out=e_out+' Its plot is: '+e['plot']
				elif e_out.endswith('Its air date is unavailable.'):
					e_out=e_out.replace('Its air date is unavailable.','Its air date and plot are unavailable.')
				else:
					e_out=e_out+' Its plot is unavailable.'
	
		else:
			if e_out!='': # Last: available; Next: unavailable
				e_out=e_out+'No upcoming episode is scheduled.'
			else: # Last: unavailable; Next: unavailable
				e_out='Episode info is unavailable for %s.'%s_title
	
		# Conditionally trim output string
		if (max_len not in [-1,0,None]) and len(e_out)>max_len-3: e_out=e_out[:max_len-3]+'...'
	
		# Return output string
		return e_out

	except:	return 'An error occurred while attempting to retrieve episode info for "%s".'%title