Check-in [7911337325]
Overview
| Comment: | more Python3 syntax fixes, introduce compat2and3 module | 
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive | 
| Timelines: | family | ancestors | descendants | both | py3 | 
| Files: | files | file ages | folders | 
| SHA1: | 
7911337325807d54a047947842f1b57a | 
| User & Date: | mario on 2014-04-08 21:50:21 | 
| Other Links: | branch diff | manifest | tags | 
Context
| 
   2014-04-08 
 | ||
| 21:53 | fix dict + dict back into list join check-in: d09e020ecf user: mario tags: py3 | |
| 21:50 | more Python3 syntax fixes, introduce compat2and3 module check-in: 7911337325 user: mario tags: py3 | |
| 21:16 | rename http to ahttp to avoid conflict with Python3 modules, change .iteritems and xrange, remove same remaining plain print statements check-in: d3b1418bc6 user: mario tags: py3 | |
Changes
Modified ahttp.py from [2dbe950381] to [11eca44aed].
1 2 3 4 5 6  | # # encoding: UTF-8 # api: streamtuner2 # type: functions # title: http download / methods # description: http utility  | | < < < < < < < < < < < < < < < < < | <  | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23  | # # encoding: UTF-8 # api: streamtuner2 # type: functions # title: http download / methods # description: http utility # version: 1.4 # # Provides a http GET method with gtk.statusbar() callback. # And a function to add trailings slashes on http URLs. # # from compat2and3 import urllib2, urlencode, urlparse, cookielib, StringIO, xrange from gzip import GzipFile from config import conf, __print__, dbg #-- url download ---------------------------------------------  | 
| ︙ | ︙ | 
Modified channels/_generic.py from [5d7f7dc2ae] to [a20153b668].
| ︙ | ︙ | |||
179 180 181 182 183 184 185  | 
        # switch stream category,
        # load data,
        # update treeview content
        def load(self, category, force=False):
        
            # get data from cache or download
 | |  | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193  | 
        # switch stream category,
        # load data,
        # update treeview content
        def load(self, category, force=False):
        
            # get data from cache or download
            if (force or not category in self.streams):
                new_streams = self.update_streams(category)
      
                if new_streams:
                
                    # modify
                    [self.postprocess(row) for row in new_streams]
      
 | 
| ︙ | ︙ | |||
233 234 235 236 237 238 239  | 
            
        # finds differences in new/old streamlist, marks deleted with flag
        def deleted_streams(self, new, old):
            diff = []
            new = [row.get("url","http://example.com/") for row in new]
            for row in old:
 | |  | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247  | 
            
        # finds differences in new/old streamlist, marks deleted with flag
        def deleted_streams(self, new, old):
            diff = []
            new = [row.get("url","http://example.com/") for row in new]
            for row in old:
                if (url in row and (row.get("url") not in new)):
                    row["deleted"] = 1
                    diff.append(row)
            return diff
        
        # prepare data for display
        def prepare(self, streams):
 | 
| ︙ | ︙ | 
Modified channels/links.py from [692f83efe7] to [e2e193464a].
| ︙ | ︙ | |||
54 55 56 57 58 59 60  | 
        bookmarks = parent.bookmarks
        if not bookmarks.streams.get(self.module):
            bookmarks.streams[self.module] = []
        bookmarks.add_category(self.module)
        # collect links from channel plugins
 | | |  | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78  | 
        bookmarks = parent.bookmarks
        if not bookmarks.streams.get(self.module):
            bookmarks.streams[self.module] = []
        bookmarks.add_category(self.module)
        # collect links from channel plugins
        for name,channel in parent.channels.items():
          try:
            self.streams.append({
                "favourite": 1,
                "title": channel.title,
                "homepage": channel.homepage,
            })
          except: pass
        for title,homepage in self.default.items():
            self.streams.append({
                "title": title,
                "homepage": homepage,
            })
        # add to bookmarks
        bookmarks.streams[self.module] = self.streams
        
        
 | 
Modified channels/myoggradio.py from [37210dae1e] to [6c4dac0144].
| ︙ | ︙ | |||
22 23 24 25 26 27 28  | from channels import * from config import conf from action import action import re import json  | |  | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36  | from channels import * from config import conf from action import action import re import json from compat2and3 import StringIO import copy # open source radio sharing stie class myoggradio(ChannelPlugin):  | 
| ︙ | ︙ | 
Modified channels/shoutcast.py from [0c3da6eedb] to [dd8d75b19e].
| ︙ | ︙ | |||
62 63 64 65 66 67 68  | 
        # sub-categories are queried per 'AJAX'
        def update_categories(self):
            html = http.get(self.base_url)
            self.categories = []
            __print__( dbg.DATA, html )
            # <h2>Radio Genres</h2>
 | | |  | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80  | 
        # sub-categories are queried per 'AJAX'
        def update_categories(self):
            html = http.get(self.base_url)
            self.categories = []
            __print__( dbg.DATA, html )
            # <h2>Radio Genres</h2>
            rx = re.compile(r'<li((?:\s+id="\d+"\s+class="files")?)><a href="\?action=sub&cat=([\w\s]+)#(\d+)">[\w\s]+</a>', re.S)
            sub = []
            for uu in rx.findall(html):
                __print__( dbg.DATA, uu )
                (main,name,id) = uu
                name = urllib.unquote(name)
                # main category
                if main:
                    if sub:
                        self.categories.append(sub)
                        sub = []
 | 
| ︙ | ︙ | 
Modified channels/timer.py from [c50adafaed] to [73a61c99cb].
| ︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29  | # # Programmed events are visible in "timer" under the "bookmarks" channel. Times # are stored in the description field, and can thus be edited. However, after editing # times manually, streamtuner2 must be restarted for the changes to take effect. # from channels import * import kronos from mygtk import mygtk from action import action import copy  | >  | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  | # # Programmed events are visible in "timer" under the "bookmarks" channel. Times # are stored in the description field, and can thus be edited. However, after editing # times manually, streamtuner2 must be restarted for the changes to take effect. # from config import __print__, dbg from channels import * import kronos from mygtk import mygtk from action import action import copy  | 
| ︙ | ︙ | |||
72 73 74 75 76 77 78  | 
            "timer_cancel": lambda w,*a: self.parent.timer_dialog.hide() or 1,
        })
        
        # prepare spool
        self.sched = kronos.ThreadedScheduler()
        for row in self.streams:
            try: self.queue(row)
 | |  | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87  | 
            "timer_cancel": lambda w,*a: self.parent.timer_dialog.hide() or 1,
        })
        
        # prepare spool
        self.sched = kronos.ThreadedScheduler()
        for row in self.streams:
            try: self.queue(row)
            except Exception as e: __print__(dbg.ERR, "queuing error", e)
        self.sched.start()
    # display GUI for setting timespec
    def edit_timer(self, *w):
        self.parent.timer_dialog.show()
        self.parent.timer_value.set_text("Fri,Sat 20:00-21:00 play")
 | 
| ︙ | ︙ | 
Added compat2and3.py version [022ad69c97].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >  | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58  | 
#
# encoding: UTF-8
# api: python 
# type: functions
# title: Python2 and Python3 compatibility
# version: 0.1
#
#  Renames some Python3 modules into their Py2 equivalent.
#  Slim local alternative to `six` module.
#
import sys
# Python 2
if sys.version_info < (3,0):
    # version tags
    PY2 = 1
    PY3 = 0
    # basic functions
    xrange = xrange
    range = xrange
    # urllib modules
    import urllib
    import urllib2
    from urllib import urlencode
    import urlparse
    import cookielib
    
    # filesys
    from StringIO import StringIO
# Python 3
else:
    # version tags
    PY2 = 0
    PY3 = 1
    # basic functions
    xrange = range
    # urllib modules
    import urllib.request as urllib
    import urllib.request as urllib2
    from urllib.parse import urlencode
    import urllib.parse as urlparse
    from http import cookiejar as cookielib
    
    # filesys
    from io import StringIO
    
 | 
Modified favicon.py from [997ecd51ce] to [983556d34c].
| ︙ | ︙ | |||
24 25 26 27 28 29 30  | always_google = 1 # use favicon service for speed only_google = 1 # if that fails, try our other/slower methods? delete_google_stub = 1 # don't keep placeholder images google_placeholder_filesizes = (726,896) import os, os.path  | |  | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38  | always_google = 1 # use favicon service for speed only_google = 1 # if that fails, try our other/slower methods? delete_google_stub = 1 # don't keep placeholder images google_placeholder_filesizes = (726,896) import os, os.path from compat2and3 import xrange, urllib import re from config import conf try: from processing import Process as Thread except: from threading import Thread import ahttp  | 
| ︙ | ︙ | 
Modified kronos.py from [6ae12b7565] to [24a87e43ef].
| ︙ | ︙ | |||
270 271 272 273 274 275 276  | 
            self.sched.queue[:] = []                    
    def _run(self):
        # Low-level run method to do the actual scheduling loop.
        while self.running:
            try:
                self.sched.run()
 | |  | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284  | 
            self.sched.queue[:] = []                    
    def _run(self):
        # Low-level run method to do the actual scheduling loop.
        while self.running:
            try:
                self.sched.run()
            except Exception as x:
                print >>sys.stderr, "ERROR DURING SCHEDULER EXECUTION",x
                print >>sys.stderr, "".join(
                    traceback.format_exception(*sys.exc_info()))
                print >>sys.stderr, "-" * 20
            # queue is empty; sleep a short while before checking again
            if self.running:
                time.sleep(5)
 | 
| ︙ | ︙ | |||
294 295 296 297 298 299 300  | 
        self.args=args
        self.kw=kw
    def __call__(self, schedulerref):
        """Execute the task action in the scheduler's thread."""
        try:
            self.execute()
 | |  | 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308  | 
        self.args=args
        self.kw=kw
    def __call__(self, schedulerref):
        """Execute the task action in the scheduler's thread."""
        try:
            self.execute()
        except Exception as x:
            self.handle_exception(x)
        self.reschedule(schedulerref())
    def reschedule(self, scheduler):
        """This method should be defined in one of the sub classes!"""
        raise NotImplementedError("You're using the abstract base class 'Task',"
            " use a concrete class instead")
 | 
| ︙ | ︙ | |||
462 463 464 465 466 467 468  | 
            self.reschedule(schedulerref())
        def threadedcall(self):
            # This method is run within its own thread, so we have to
            # do the execute() call and exception handling here.
            try:
                self.execute()
 | |  | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476  | 
            self.reschedule(schedulerref())
        def threadedcall(self):
            # This method is run within its own thread, so we have to
            # do the execute() call and exception handling here.
            try:
                self.execute()
            except Exception as x:
                self.handle_exception(x)
    class ThreadedIntervalTask(ThreadedTaskMixin, IntervalTask):
        """Interval Task that executes in its own thread."""
        pass
    class ThreadedSingleTask(ThreadedTaskMixin, SingleTask):
 | 
| ︙ | ︙ | |||
529 530 531 532 533 534 535  | 
        def __call__(self, schedulerref):
            """Execute the task action in its own process."""
            pid = os.fork()
            if pid == 0:
                # we are the child
                try:
                    self.execute()
 | |  | 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543  | 
        def __call__(self, schedulerref):
            """Execute the task action in its own process."""
            pid = os.fork()
            if pid == 0:
                # we are the child
                try:
                    self.execute()
                except Exception as x:
                    self.handle_exception(x)
                os._exit(0)
            else:
                # we are the parent
                self.reschedule(schedulerref())
 | 
| ︙ | ︙ | 
Modified pq.py from [774d8a07cf] to [9ad9a3d426].
| ︙ | ︙ | |||
15 16 17 18 19 20 21  | 
try:
    from pyquery import PyQuery as pq
    # pq.each_pq = lambda self,func:  self.each(   lambda i,html: func( pq(html, parser="html") )   )
 | |  | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29  | 
try:
    from pyquery import PyQuery as pq
    # pq.each_pq = lambda self,func:  self.each(   lambda i,html: func( pq(html, parser="html") )   )
except Exception as e:
    # disable use
    pq = None
    config.conf.pyquery = False
    # error hint
    print("LXML is missing\n", e)
 | 
| ︙ | ︙ | 
Modified st2.py from [1b132a9fda] to [9090947823].
| ︙ | ︙ | |||
216 217 218 219 220 221 222  | 
                "search_google": search.google,
                "search_cancel": search.cancel,
                "true": lambda w,*args: True,
                "streamedit_open": streamedit.open,
                "streamedit_save": streamedit.save,
                "streamedit_new": streamedit.new,
                "streamedit_cancel": streamedit.cancel,
 | |  | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230  | 
                "search_google": search.google,
                "search_cancel": search.cancel,
                "true": lambda w,*args: True,
                "streamedit_open": streamedit.open,
                "streamedit_save": streamedit.save,
                "streamedit_new": streamedit.new,
                "streamedit_cancel": streamedit.cancel,
            }.items() | self.add_signals.items() ))
            
            # actually display main window
            gui_startup(99/100.0)
            self.win_streamtuner2.show()
            
            # WHY DON'T YOU WANT TO WORK?!
            #self.shoutcast.gtk_list.set_enable_search(True)
 | 
| ︙ | ︙ | |||
521 522 523 524 525 526 527  | 
                        gtk.rc_parse(f)
                pass
        # end application and gtk+ main loop
        def gtk_main_quit(self, widget, *x):
            if conf.auto_save_appstate:
 | |  | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535  | 
                        gtk.rc_parse(f)
                pass
        # end application and gtk+ main loop
        def gtk_main_quit(self, widget, *x):
            if conf.auto_save_appstate:
                try:  # doesn't work with gtk3 yet (probably just hooking at the wrong time)
                    self.app_state(widget)
                except:
                    None
            gtk.main_quit()
 | 
| ︙ | ︙ |