Skip to content

Commit

Permalink
Migration to python 3, courtesy of Chris Branner
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Brannon authored and halhen committed Nov 4, 2010
1 parent 43c9ef9 commit 95fca16
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 44 deletions.
5 changes: 5 additions & 0 deletions AUTHORS
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,5 @@
Author of shoutcast-search:
Henrik Hallberg <halhen@k2h.se> 2009-2010

Migration from python2 to python3:
Christopher Brannon <chris AT the-brannons DOT com> 2010
64 changes: 32 additions & 32 deletions shoutcast-search
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@


import re import re
import sys import sys
import urllib2 import urllib.error
import random import random
import optparse import optparse


Expand Down Expand Up @@ -52,25 +52,25 @@ def _station_text(station_info, format):
return resstr return resstr


def _fail_exit(code, msg): def _fail_exit(code, msg):
sys.stderr.write("%s: %s\n" % (sys.argv[0], msg)) sys.stderr.write("{0}: {1}\n".format(sys.argv[0], msg))
sys.exit(code) sys.exit(code)


def _expression_param(value): def _expression_param(value):
if not value: if not value:
return lambda(x):True return lambda x:True
if not re.compile('^[=><]?\d+$').match(value): if not re.compile('^[=><]?\d+$').match(value):
o.error('invalid expression: %s' % value) o.error('invalid expression: {0}'.format(value))


if value[0] in ('><'): if value[0] in ('><'):
return lambda(x): eval('%s%s' % (x, value)) return lambda x: eval('{0}{1}'.format(x, value))
else: else:
return lambda(x): eval('%s==%s' % (x, value.strip('='))) return lambda x: eval('{0}=={1}'.format(x, value.strip('=')))


def _int_param(value): def _int_param(value):
try: try:
return int(value) return int(value)
except: except:
o.error('invalid integer: %s' % value) o.error('invalid integer: {0}'.format(value))


def _generate_list_sorters(pattern = 'l'): def _generate_list_sorters(pattern = 'l'):
''' '''
Expand All @@ -97,7 +97,7 @@ def _generate_list_sorters(pattern = 'l'):
descending_text = 'desc' descending_text = 'desc'
if not descending: if not descending:
descending_text = 'asc' descending_text = 'asc'
return '%s %s' % (fieldname, descending_text) return '{0} {1}'.format(fieldname, descending_text)


def _random(list): def _random(list):
random.shuffle(list) random.shuffle(list)
Expand Down Expand Up @@ -134,12 +134,12 @@ def _generate_list_sorters(pattern = 'l'):
index -= 1 index -= 1


if not number: if not number:
o.error('missing number for sorter n in "%s"' % pattern) o.error('missing number for sorter n in "{0}"'.format(pattern))
value = int(number) value = int(number)
sorters.append(lambda list: list[:value]) sorters.append(lambda list: list[:value])
sorters_description.append('top %s' % value) sorters_description.append('top {0}'.format(value))
else: else:
o.error('invalid sorter: %s' % char) o.error('invalid sorter: {0}'.format(char))


if char != '^': if char != '^':
sort_descending = True # Reset sort order sort_descending = True # Reset sort order
Expand Down Expand Up @@ -189,7 +189,7 @@ if __name__ == '__main__':
try: try:
if options.do_list_genres: if options.do_list_genres:
genres = scs.get_genres() genres = scs.get_genres()
print '\n'.join(genres) print('\n'.join(genres))
if genres: if genres:
sys.exit(0) sys.exit(0)
else: else:
Expand Down Expand Up @@ -224,43 +224,43 @@ if __name__ == '__main__':


if p_verbose: if p_verbose:
# Print information about query to help debug # Print information about query to help debug
print 'Search summary' print('Search summary')
print '-' * 30 print('-' * 30)
print ' Keywords: %s' % ', '.join(p_keywords) print(' Keywords: {0}'.format(', '.join(p_keywords)))
print ' Genres: %s' % ', '.join(p_genre) print(' Genres: {0}'.format(', '.join(p_genre)))
print ' Playing: %s' % ', '.join(p_song) print(' Playing: {0}'.format(', '.join(p_song)))
print ' Stations: %s' % ', '.join(p_station) print(' Stations: {0}'.format(', '.join(p_station)))
bitrate_str = '' bitrate_str = ''
if options.bitrate: if options.bitrate:
bitrate_str = options.bitrate bitrate_str = options.bitrate
print ' Bitrate: %s' % bitrate_str print(' Bitrate: {0}'.format(bitrate_str))
listeners_str = '' listeners_str = ''
if options.listeners: if options.listeners:
listeners_str = options.listeners listeners_str = options.listeners
print 'Listeners: %s' % listeners_str print('Listeners: {0}'.format(listeners_str))
print ' Type: %s' % options.codec print(' Type: {0}'.format(options.codec))
order_str = 'by no listeners' order_str = 'by no listeners'
if p_random: if p_random:
order_str = 'random' order_str = 'random'
if p_sort_rules: if p_sort_rules:
order_str = 'by sorters' order_str = 'by sorters'
print ' Order: %s' % order_str print(' Order: {0}'.format(order_str))
print ' Sorter: %s' % (' | '.join(sorters_description)) print(' Sorter: {0}'.format(' | '.join(sorters_description)))
limit_str = '' limit_str = ''
if p_limit > 0: if p_limit > 0:
limit_str = str(p_limit) limit_str = str(p_limit)
print ' Limit: %s' % limit_str print(' Limit: {0}'.format(limit_str))
print ' Format: %s' % p_format print(' Format: {0}'.format(p_format))
print '' print('')


results = scs.search(p_keywords, p_station, p_genre, p_song, p_bitrate, p_listeners, p_mime_type, p_limit, p_random, sorters) results = scs.search(p_keywords, p_station, p_genre, p_song, p_bitrate, p_listeners, p_mime_type, p_limit, p_random, sorters)


print '\n'.join(_station_text(el, p_format) for el in results) print('\n'.join(_station_text(el, p_format) for el in results))
if p_verbose: if p_verbose:
print '\n%s station(s) found.' % len(results) print('\n{0:d} station(s) found.'.format(len(results)))
if not results: if not results:
_fail_exit(4, 'no station found\n') _fail_exit(4, 'no station found\n')
except urllib2.URLError, e: except urllib.error.URLError as e:
_fail_exit(1, 'network error: %s' % e) _fail_exit(1, 'network error: {0}'.format(e))
except Exception, e: except Exception as e:
_fail_exit(3, 'unknown error: %s' % e) _fail_exit(3, 'unknown error: {0}'.format(e))
2 changes: 1 addition & 1 deletion shoutcast_search/__init__.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


__version__ = 'CURVERSION' __version__ = 'CURVERSION'


import shoutcast_search from . import shoutcast_search


def main(): def main():
pass pass
Expand Down
24 changes: 13 additions & 11 deletions shoutcast_search/shoutcast_search.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,34 +21,36 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #


import urllib import urllib.request, urllib.parse, urllib.error
import urllib2
import re import re
import random import random
from htmlentitydefs import name2codepoint from html.entities import name2codepoint

def _from_UTF_8(inbytes):
return str(inbytes, 'UTF-8')


def _build_search_url(params): def _build_search_url(params):
''' '''
Return URL to search web service with appropriately encoded parameters. Return URL to search web service with appropriately encoded parameters.
params - See urllib.urlencode params - See urllib.urlencode
''' '''
baseurl = 'http://yp.shoutcast.com/sbin/newxml.phtml?' baseurl = 'http://yp.shoutcast.com/sbin/newxml.phtml?'
params_str = urllib.urlencode(params) params_str = urllib.parse.urlencode(params)
return baseurl + params_str return baseurl + params_str


def _decode_entities(s): def _decode_entities(s):
''' '''
Return string with converted htmlentities, e.g. &auml; Return string with converted htmlentities, e.g. &auml;
s - string to convert s - string to convert
''' '''
return re.sub('&(%s);'% ('|'.join(name2codepoint)), lambda(m): chr(name2codepoint[m.group(1)]), s) return re.sub('&(%s);'% ('|'.join(name2codepoint)), lambda m: chr(name2codepoint[m.group(1)]), s)


def _retrieve_search_results(params): def _retrieve_search_results(params):
''' '''
Perform search against shoutcast.com web service. Perform search against shoutcast.com web service.
params - See urllib.urlencode and http://forums.winamp.com/showthread.php?threadid=295638 params - See urllib.urlencode and http://forums.winamp.com/showthread.php?threadid=295638
''' '''
content = urllib2.urlopen(_build_search_url(params)).read() content = _from_UTF_8(urllib.request.urlopen(_build_search_url(params)).read())


lp = re.compile('<station ') lp = re.compile('<station ')
p = re.compile(' (.*?)=\"(.*?)\"') p = re.compile(' (.*?)=\"(.*?)\"')
Expand All @@ -72,17 +74,17 @@ def url_by_id(index):
''' '''
Returns the stations URL based on its ID Returns the stations URL based on its ID
''' '''
return 'http://yp.shoutcast.com/sbin/tunein-station.pls?id=%s' % index return 'http://yp.shoutcast.com/sbin/tunein-station.pls?id={0}'.format(index)


def get_genres(): def get_genres():
''' '''
Returns a list of genres (listed by the shoutcast web service). Returns a list of genres (listed by the shoutcast web service).
Raises urllib2.URLError if network communication fails Raises urllib2.URLError if network communication fails
''' '''
content = urllib2.urlopen('http://yp.shoutcast.com/sbin/newxml.phtml').read() content = _from_UTF_8(urllib.request.urlopen('http://yp.shoutcast.com/sbin/newxml.phtml').read())
return list(re.compile('<genre name="(.*?)"').findall(content)) return list(re.compile('<genre name="(.*?)"').findall(content))


def search(search = [], station = [], genre = [], song = [], bitrate_fn = lambda(x): True, listeners_fn = lambda(x): True, mime_type = '', limit = 0, randomize = False, sorters = []): def search(search = [], station = [], genre = [], song = [], bitrate_fn = lambda x: True, listeners_fn = lambda x: True, mime_type = '', limit = 0, randomize = False, sorters = []):
''' '''
Search shoutcast.com for streams with given criteria. See http://forums.winamp.com/showthread.php?threadid=295638 for details and rules. Raises urllib2.URLError if network communication fails. Search shoutcast.com for streams with given criteria. See http://forums.winamp.com/showthread.php?threadid=295638 for details and rules. Raises urllib2.URLError if network communication fails.
search - List of free-form keywords. Searches in station names, genres and songs. search - List of free-form keywords. Searches in station names, genres and songs.
Expand Down Expand Up @@ -140,13 +142,13 @@ def search(search = [], station = [], genre = [], song = [], bitrate_fn = lambda
for s in song: for s in song:
results = [r for r in results if s.upper() in r['ct'].upper()] results = [r for r in results if s.upper() in r['ct'].upper()]
for k in keywords: for k in keywords:
results = [r for r in results if k.upper() in ('%s %s %s' % (r['name'], r['genre'], r['ct'])).upper()] results = [r for r in results if k.upper() in '{0} {1} {2}'.format(r['name'], r['genre'], r['ct']).upper()]


if randomize: if randomize:
random.shuffle(results) random.shuffle(results)
else: else:
# Sort by listener count # Sort by listener count
results.sort(lambda a, b: cmp(int(a['lc']), int(b['lc'])), reverse=True) results.sort(key=lambda x: int(x['lc']), reverse=True)


for m in sorters: for m in sorters:
results = m(results) results = m(results)
Expand Down

0 comments on commit 95fca16

Please sign in to comment.