Internet radio browser GUI for music/video streams from various directory services.

⌈⌋ ⎇ branch:  streamtuner2


Check-in [5588baf6dd]

Overview
Comment:Implement custom HTML .entitiy_decode, because SAX didn't honor any HTML; and HTMLParser would require customized/compat2and3 imports.

Colorize channel labels if #color: is specified in any plugins.

And provide @use_rx decorator to alternate between regex/pyquery extractors.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5588baf6ddaf530008bae6ccba1dfbf259a37285
User & Date: mario on 2015-05-02 05:41:54
Other Links: manifest | tags
Context
2015-05-02
05:42
Use new @use_rx decorator to switch and fall back between regex/pyquery modes. check-in: f269792f36 user: mario tags: trunk
05:41
Implement custom HTML .entitiy_decode, because SAX didn't honor any HTML; and HTMLParser would require customized/compat2and3 imports.

Colorize channel labels if #color: is specified in any plugins.

And provide @use_rx decorator to alternate between regex/pyquery extractors. check-in: 5588baf6dd user: mario tags: trunk

05:39
More specific log.HTTP messages (GET vs POST) check-in: 8ede46a0a1 user: mario tags: trunk
Changes

Modified channels/__init__.py from [5eb841253c] to [0f18034c13].

31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







-
+







import gtk
from uikit import uikit, ver as gtk_ver
from config import *
import ahttp
import action
import favicon
import os.path
import xml.sax.saxutils
import xml.sax.saxutils, htmlentitydefs
import re
import copy
import inspect


# Only export plugin classes
__all__ = [
    "GenericChannel", "ChannelPlugin"
    "GenericChannel", "ChannelPlugin", "use_rx"
]



# generic channel module                            ---------------------------------------
class GenericChannel(object):

573
574
575
576
577
578
579
580
581










582
583
584
585
586
587
588
573
574
575
576
577
578
579


580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596







-
-
+
+
+
+
+
+
+
+
+
+







        # add prefix:
        if s.find("/") < 1:
            s = "audio/" + s
        #
        return s
    
    # remove SGML/XML entities
    def entity_decode(self, s):
        return xml.sax.saxutils.unescape(s).replace("&nbsp;", " ")
    def entity_decode(self, str):
        return re.sub('&(#?(x?))(\w+);', self._entity, str)
    def _entity(self, sym):
        num, hex, name = sym.groups()
        if hex:
            return unichr(int(name, base=16))
        elif num:
            return unichr(int(name))
        else:
            return unichr(htmlentitydefs.name2codepoint[name])
    
    # convert special characters to &xx; escapes
    def xmlentities(self, s):
        return xml.sax.saxutils.escape(s)
    
    # Extracts integer from string
    def to_int(self, s):
646
647
648
649
650
651
652
653




654
655
656
657
658
659
660
654
655
656
657
658
659
660

661
662
663
664
665
666
667
668
669
670
671







-
+
+
+
+







            pixbuf = uikit.pixbuf(png)
        if pixbuf:
            icon = gtk.image_new_from_pixbuf(pixbuf)
        else:
            icon = gtk.image_new_from_stock(gtk.STOCK_DIRECTORY, size=1)
        label = gtk.HBox()
        label.pack_start(icon, expand=False, fill=True)
        label.pack_start(gtk.Label(self.meta.get("title", self.module)), expand=True, fill=True)
        l = gtk.Label(self.meta.get("title", self.module))
        if self.meta.get("color"):
            l = uikit.bg(l, self.meta["color"])
        label.pack_start(l, expand=True, fill=True)
            
        # pack it into an event container to catch double-clicks
        ev_label = gtk.EventBox()
        ev_label.add(label)
        ev_label.connect('event', parent.on_homepage_channel_clicked)
        plain_label = gtk.Label(self.module)

684
685
686
687
688
689
690
691















695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
def stub_parent(object):
    def __setattr__(self, name, value):
        pass
    def __getattr__(self, name):
        return lambda *x: None
    def status(self, *x):
        pass


# Decorator
def use_rx(func):
    def try_both(*args, **kwargs):
        for method, use_rx in [("RX", not conf.pyquery), ("PQ", conf.pyquery)]:
            try:
                log.STAT(method)
                return func(*args, use_rx=not conf.pyquery, **kwargs)
            except Exception as e:
                log.ERR("{} extraction failed:".format(method), e)
                continue
        return []
    return try_both