grail.py :  » Network » Grail-Internet-Browser » grail-0.6 » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Grail Internet Browser 
Grail Internet Browser » grail 0.6 » grail.py
#! /usr/bin/env python

"""Grail -- the Extensible Internet Browser."""


# Version string in a form ready for the User-agent HTTP header
__version__ = "Grail/0.6"
GRAILVERSION = __version__

# Standard python imports (needed by path munging code)
import os
import sys

# Path munging
if __name__ == '__main__':
    script_name = sys.argv[0]
    while 1:
        script_dir = os.path.dirname(script_name)
        if not os.path.islink(script_name):
            break
        script_name = os.path.join(script_dir, os.readlink(script_name))
    script_dir = os.path.join(os.getcwd(), script_dir)
    script_dir = os.path.normpath(script_dir)
    grail_root = script_dir
else:
    script_dir = os.path.dirname(__file__)
    grail_root = script_dir
for path in 'utils', 'pythonlib', 'ancillary', 'applets', script_dir:
    sys.path.insert(0, os.path.join(grail_root, path))

import getopt
import string
import urllib
import tempfile
import posixpath

# More imports
import filetypes
import grailbase.utils
# TBD: hack!
grailbase.utils._grail_root = grail_root
import grailutil
from Tkinter import *
import tktools
import BaseApplication
import grailbase.GrailPrefs
import Stylesheet
from CacheMgr import CacheManager
from ImageCache import ImageCache
from Authenticate import AuthenticationManager
import GlobalHistory

# Milliseconds between interrupt checks
KEEPALIVE_TIMER = 500

# Command line usage message
USAGE = """Usage: %s [options] [url]
Options:
    -i, --noimages : inhibit loading of images
    -g <geom>, --geometry <geom> : initial window geometry
    -d <display>, --display <display> : override $DISPLAY
    -q : ignore user's grailrc module""" % sys.argv[0]

def main(args=None):
    prefs = grailbase.GrailPrefs.AllPreferences()
    # XXX Disable cache for NT
    if sys.platform == 'win32':
        prefs.Set('disk-cache', 'size', '0')
    global ilu_tk
    ilu_tk = 0
    if prefs.GetBoolean('security', 'enable-ilu'):
        try: import ilu_tk
        except ImportError: pass
    if args is not None:
        embedded = 1
    else:
        args = sys.argv[1:]
        embedded = 0
    try:
        opts, args = getopt.getopt(args, 'd:g:iq',
                                   ['display=', 'geometry=', 'noimages'])
        if len(args) > 1:
            raise getopt.error, "too many arguments"
    except getopt.error, msg:
        sys.stdout = sys.stderr
        print "Command line error:", msg
        print USAGE
        sys.exit(2)

    geometry = prefs.Get('browser', 'initial-geometry')
    display = None
    user_init = 1

    for o, a in opts:
        if o in ('-i', '--noimages'):
            load_images = 0
        if o in ('-g', '--geometry'):
            geometry = a
        if o in ('-d', '--display'):
            display = a
        if o == "-q":
            user_init = 0
    if args:
        url = grailutil.complete_url(args[0])
    else:
        url = None
    global app
    app = Application(prefs=prefs, display=display)
    app.embedded = embedded
    if __name__ != '__main__':
        import __main__
        __main__.app = app
        __main__.GRAILVERSION = GRAILVERSION

    def load_images_vis_prefs(app=app):
        app.load_images = app.prefs.GetBoolean('browser', 'load-images')
    try:
        app.load_images = load_images
    except NameError:
        load_images_vis_prefs()
    prefs.AddGroupCallback('browser', load_images_vis_prefs)

    import SafeTkinter
    SafeTkinter._castrate(app.root.tk)

    tktools.install_keybindings(app.root)

    # Make everybody who's still using urllib.urlopen go through the cache
    urllib.urlopen = app.open_url_simple

    # Add $GRAILDIR/user/ to sys.path
    subdir = os.path.join(app.graildir, 'user')
    if subdir not in sys.path:
        sys.path.insert(0, subdir)

    # Import user's grail startup file, defined as
    # $GRAILDIR/user/grailrc.py if it exists.
    if user_init:
        try: import grailrc
        except ImportError, e:
            # Only catch this is grailrc itself doesn't import,
            # otherwise propogate.
            if string.split(e.args[0])[-1] != "grailrc":
                raise
        except:
            app.exception_dialog('during import of startup file')

    # Load the initial page (command line argument or from preferences)
    if not embedded:
        from Browser import Browser
        browser = Browser(app.root, app, geometry=geometry)
        if url:
            browser.context.load(url)
        elif prefs.GetBoolean('browser', 'load-initial-page'):
            browser.home_command()

    if not embedded:
        # Give the user control
        app.go()


class URLReadWrapper:

    def __init__(self, api, meta):
        self.api = api
        self.meta = meta
        self.eof = 0

    def read(self, nbytes=-1):
        buf = ''
        BUFSIZ = 8*1024
        while nbytes != 0 and not self.eof:
            new = self.api.getdata(nbytes < 0 and BUFSIZ or nbytes)
            if not new:
                self.eof = 1
                break
            buf = buf + new
            if nbytes > 0:
                nbytes - nbytes - len(new)
                if nbytes <= 0:
                    break
        return buf

    def info(self):
        return self.meta

    def close(self):
        api = self.api
        self.api = None
        self.meta = None
        if api:
            api.close()

class SocketQueue:

    def __init__(self, max_sockets):
        self.max = max_sockets
        self.blocked = []
        self.callbacks = {}
        self.open = 0

    def change_max(self, new_max):
        old_max = self.max
        self.max = new_max
        if old_max < new_max and len(self.blocked) > 0:
            for i in range(0,min(new_max-old_max, len(self.blocked))):
                # run wild free sockets
                self.open = self.open + 1
                self.callbacks[self.blocked[0]]()
                del self.callbacks[self.blocked[0]]
                del self.blocked[0]
            

    def request_socket(self, requestor, callback):
        if self.open >= self.max:
            self.blocked.append(requestor)
            self.callbacks[requestor] = callback
        else:
            self.open = self.open + 1
            callback()

    def return_socket(self, owner):
        if owner in self.blocked:
            # died before its time
            self.blocked.remove(owner)
            del self.callbacks[owner]
        elif len(self.blocked) > 0:
            self.callbacks[self.blocked[0]]()  # apply callback
            del self.callbacks[self.blocked[0]]
            del self.blocked[0]
        else:
            self.open = self.open - 1

class Application(BaseApplication.BaseApplication):

    """The application class represents a group of browser windows."""

    def __init__(self, prefs=None, display=None):
        self.root = Tk(className='Grail', screenName=display)
        self.root.withdraw()
        resources = os.path.join(script_dir, "data", "Grail.ad")
        if os.path.isfile(resources):
            self.root.option_readfile(resources, "startupFile")
        BaseApplication.BaseApplication.__init__(self, prefs)
        # The stylesheet must be initted before any Viewers, so it
        # registers its' prefs callbacks first, hence reloads before the
        # viewers reconfigure w.r.t. the new styles.
        self.stylesheet = Stylesheet.Stylesheet(self.prefs)
        self.load_images = 1            # Overridden by cmd line or pref.

        # socket management
        sockets = self.prefs.GetInt('sockets', 'number')
        self.sq = SocketQueue(sockets)
        self.prefs.AddGroupCallback('sockets',
                                    lambda self=self: \
                                    self.sq.change_max(
                                        self.prefs.GetInt('sockets',
                                                          'number')))

        # initialize on_exit_methods before global_history
        self.on_exit_methods = []
        self.global_history = GlobalHistory.GlobalHistory(self)
        self.login_cache = {}
        self.rexec_cache = {}
        self.url_cache = CacheManager(self)
        self.image_cache = ImageCache(self.url_cache)
        self.auth = AuthenticationManager(self)
        self.root.report_callback_exception = self.report_callback_exception
        if sys.stdin.isatty():
            # only useful if stdin might generate KeyboardInterrupt
            self.keep_alive()
        self.browsers = []
        self.iostatuspanel = None
        self.in_exception_dialog = None
        import Greek
        for k, v in Greek.entitydefs.items():
            Application.dingbatimages[k] = (v, '_sym')
        self.root.bind_class("Text", "<Alt-Left>", self.dummy_event)
        self.root.bind_class("Text", "<Alt-Right>", self.dummy_event)

    def dummy_event(self, event):
        pass

    def register_on_exit(self, method):
        self.on_exit_methods.append(method)
    def unregister_on_exit(self, method):
        try: self.on_exit_methods.remove(method)
        except ValueError: pass
    def exit_notification(self):
        for m in self.on_exit_methods[:]:
            try: m()
            except: pass

    def add_browser(self, browser):
        self.browsers.append(browser)

    def del_browser(self, browser):
        try: self.browsers.remove(browser)
        except ValueError: pass

    def quit(self):
        self.root.quit()

    def open_io_status_panel(self):
        if not self.iostatuspanel:
            import IOStatusPanel
            self.iostatuspanel = IOStatusPanel.IOStatusPanel(self)
        else:
            self.iostatuspanel.reopen()

    def maybe_quit(self):
        if not (self.embedded or self.browsers):
            self.quit()

    def go(self):
        try:
            try:
                if ilu_tk:
                    ilu_tk.RunMainLoop()
                else:
                    self.root.mainloop()
            except KeyboardInterrupt:
                pass
        finally:
            self.exit_notification()

    def keep_alive(self):
        # Exercise the Python interpreter regularly so keyboard
        # interrupts get through
        self.root.tk.createtimerhandler(KEEPALIVE_TIMER, self.keep_alive)

    def get_cached_image(self, url):
        return self.image_cache.get_image(url)

    def set_cached_image(self, url, image, owner=None):
        self.image_cache.set_image(url, image, owner)

    def open_url(self, url, method, params, reload=0, data=None):
        api = self.url_cache.open(url, method, params, reload, data=data)
        api._url_ = url
        return api

    def open_url_simple(self, url):
        api = self.open_url(url, 'GET', {})
        errcode, errmsg, meta = api.getmeta()
        if errcode != 200:
            raise IOError, ('url open error', errcode, errmsg, meta)
        return URLReadWrapper(api, meta)

    def get_cache_keys(self):
        """For applets."""
        return self.url_cache.items.keys()

    def decode_pipeline(self, fp, content_encoding, error=1):
        if self.decode_prog.has_key(content_encoding):
            prog = self.decode_prog[content_encoding]
            if not prog: return fp
            tfn = tempfile.mktemp()
            ok = 0
            try:
                temp = open(tfn, 'w')
                BUFSIZE = 8192
                while 1:
                        buf = fp.read(BUFSIZE)
                        if not buf: break
                        temp.write(buf)
                temp.close()
                ok = 1
            finally:
                if not ok:
                    try:
                        os.unlink(tfn)
                    except os.error:
                        pass
            pipeline = '%s <%s; rm -f %s' % (prog, tfn, tfn)
            # XXX What if prog fails?
            return os.popen(pipeline, 'r')
        if error:
            self.error_dialog(IOError,
                "Can't decode content-encoding: %s" % content_encoding)
        return None

    decode_prog = {
        'gzip': 'gzip -d',
        'x-gzip': 'gzip -d',
        'compress': 'compress -d',
        'x-compress': 'compress -d',
        }

    def exception_dialog(self, message="", root=None):
        exc, val, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
        self.exc_dialog(message, exc, val, tb, root)

    def report_callback_exception(self, exc, val, tb, root=None):
        self.exc_dialog("in a callback function", exc, val, tb, root)

    def exc_dialog(self, message, exc, val, tb, root=None):
        if self.in_exception_dialog:
            print
            print "*** Recursive exception", message
            import traceback
            traceback.print_exception(exc, val, tb)
            return
        self.in_exception_dialog = 1
        def f(s=self, m=message, e=exc, v=val, t=tb, root=root):
            s._exc_dialog(m, e, v, t, root)
        if TkVersion >= 4.1:
            self.root.after_idle(f)
        else:
            self.root.after(0, f)

    def _exc_dialog(self, message, exc, val, tb, root=None):
        # XXX This needn't be a modal dialog --
        # XXX should SafeDialog be changed to support callbacks?
        import SafeDialog
        msg = "An exception occurred " + str(message) + " :\n"
        msg = msg + str(exc) + " : " + str(val)
        dlg = SafeDialog.Dialog(root or self.root,
                                text=msg,
                                title="Python Exception: " + str(exc),
                                bitmap='error',
                                default=0,
                                strings=("OK", "Show traceback"),
                                )
        self.in_exception_dialog = 0
        if dlg.num == 1:
            self.traceback_dialog(exc, val, tb)

    def traceback_dialog(self, exc, val, tb):
        # XXX This could actually just create a new Browser window...
        import TbDialog
        TbDialog.TracebackDialog(self.root, exc, val, tb)

    def error_dialog(self, exc, msg, root=None):
        # Display an error dialog.
        # Return when the user clicks OK
        # XXX This needn't be a modal dialog
        import SafeDialog
        if type(msg) in (ListType, TupleType):
            s = ''
            for item in msg:
                s = s + ':\n' + str(item)
            msg = s[2:]
        else:
            msg = str(msg)
        SafeDialog.Dialog(root or self.root,
                      text=msg,
                      title="Error: " + str(exc),
                      bitmap='error',
                      default=0,
                      strings=('OK',),
                      )

    dingbatimages = {'ldots': ('...', None),    # math stuff
                     'sp': (' ', None),
                     'hairsp': ('\240', None),
                     'thinsp': ('\240', None),
                     'emdash': ('--', None),
                     'endash': ('-', None),
                     'mdash': ('--', None),
                     'ndash': ('-', None),
                     'ensp': (' ', None)
                     }

    def clear_dingbat(self, entname):
        if self.dingbatimages.has_key(entname):
            del self.dingbatimages[entname]

    def set_dingbat(self, entname, entity):
        self.dingbatimages[entname] = entity

    def load_dingbat(self, entname):
        if self.dingbatimages.has_key(entname):
            return self.dingbatimages[entname]
        gifname = grailutil.which(entname + '.gif', self.iconpath)
        if gifname:
            img = PhotoImage(file=gifname, master=self.root)
            self.dingbatimages[entname] = img
            return img
        self.dingbatimages[entname] = None
        return None


if __name__ == "__main__":
    if sys.argv[1:] and sys.argv[1][:2] == '-p':
        p = sys.argv[1]
        del sys.argv[1]
        if p[2:]: n = eval(p[2:])
        else: n = 20
        KEEPALIVE_TIMER = 50000
        import profile
        profile.run('main()', '@grail.prof')
        import pstats
        p = pstats.Stats('@grail.prof')
        p.strip_dirs().sort_stats('time').print_stats(n)
        p.print_callers(n)
        p.strip_dirs().sort_stats('cum').print_stats(n)
    else:
        main()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.