"""This file defines
   - a class : MyHTMLParser,
   - a method to parse a html url (using this class)
   and a test method to this class.
"""

# Copyright (c) 2001 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

from htmllib import HTMLParser

class MyHTMLParser(HTMLParser):
    """This class provides all data text available in an html url.
       It herits from HTMLParser class (python modules).
       To insist on the important text, it's rewrite 2 times again (nb_times).
       An important text should be : title, b, i, em, and h1...h6.
       And it's use the alt attribut in the img tags.
    """
    
    def __init__(self, formatter, debug=0):
        HTMLParser.__init__(self, formatter, debug)
        self.code = 0        # default: this isn't code
        self.important = 0   # default: this isn't important
        self.go = 0          # default: this isn't things in buffer
        self.buffer = ' '    # default: the buffer is empty
        self.nb_times = 2    # number repeats important text

    # --- Hooks for anchors;

    def anchor_bgn(self, href, name, type):
        pass

    def anchor_end(self):
        pass

    # --- Hook for images;

    def handle_image(self, src, alt, *args):
        pass

    # --- Hook for listening;

    def start_script(self,attrs):
        # Callback at the begining of the script
        # Take care, this is a script
        self.code = 1

    def end_script(self):
        # Callback at the end of the script
        # Now, the script finishes
        self.code = 0

    def start_style(self,attrs):
        # Callback at the begining of the code
        # Take care, this is a code
        self.code = 1

    def end_style(self):
        # Callback at the end of the code
        # Now, the code finishes
        self.code = 0

    def handle_data(self,data):
        # Do not parse if script tag
        if not self.code:
            if self.go:
                self.go = 0
                # copy several times data if it's important
                self.buffer = self.buffer + ' '
                for i in range(self.nb_times):
                    HTMLParser.handle_data(self,self.buffer)
                self.buffer = ' '
            HTMLParser.handle_data(self,data)
            if self.important:
                self.buffer = self.buffer + data

    def start_title(self,attrs):
        # Callback at the begining of the title
        self.important = 1

    def end_title(self):
        # Callback at the end of the title
        self.important = 0
        self.go = 1

    def start_b(self,attrs):
        # Callback at the begining of the bold text
        self.important = 1

    def end_b(self):
        # Callback at the end of the bold text
        self.important = 0
        self.go = 1

    def start_i(self,attrs):
        # Callback at the begining of the i
        self.important = 1

    def end_i(self):
        # Callback at the end of the i
        self.important = 0
        self.go = 1

    def start_em(self,attrs):
        # Callback at the begining of the emphasis
        self.important = 1

    def end_em(self):
        # Callback at the end of the emphasis
        self.important = 0
        self.go = 1

    def do_img(self,attrs):
        # Callback at the begining of the img
        for attrname, value in attrs:
            if attrname == 'alt':
                tmp = self.rawdata # for special character
                self.rawdata = value
                self.goahead(0)
                self.rawdata = tmp

    def start_h1(self,attrs):
        # Callback at the begining of the h1
        self.important = 1

    def end_h1(self):
        # Callback at the end of the h1
        self.important = 0
        self.go = 1

    def start_h2(self,attrs):
        # Callback at the begining of the h2
        self.important = 1

    def end_h2(self):
        # Callback at the end of the h2
        self.important = 0
        self.go = 1

    def start_h3(self,attrs):
        # Callback at the begining of the h3
        self.important = 1

    def end_h3(self):
        # Callback at the end of the h3
        self.important = 0
        self.go = 1

    def start_h4(self,attrs):
        # Callback at the begining of the h4
        self.important = 1

    def end_h4(self):
        # Callback at the end of the h4
        self.important = 0
        self.go = 1

    def start_h5(self,attrs):
        # Callback at the begining of the h5
        self.important = 1

    def end_h5(self):
        # Callback at the end of the h5
        self.important = 0
        self.go = 1

    def start_h6(self,attrs):
        # Callback at the begining of the h6
        self.important = 1

    def end_h6(self):
        # Callback at the end of the h6
        self.important = 0
        self.go = 1




def parse_html_url(url, debug=0):
    # Parse an html url
    # if not debug => return a StringO at end
    # if debug => print the data text
    from urllib import urlopen
    from sys import exit, stdin
    from cStringIO import StringIO
    from formatter import AbstractFormatter, DumbWriter
    print 'Opening',url
    try:
        f = urlopen(url)
    except IOError, msg:
        if debug:
            print msg
        raise ReadError()
    
    html_data = f.read().replace('\0','')
    
    if f is not stdin:
        f.close()
    
    if debug:
        form = AbstractFormatter(DumbWriter())
    else:
        data = StringIO()
        form = AbstractFormatter(DumbWriter(data))
    
    if debug:
        print '--'*35
        print url
    
    p = MyHTMLParser(form)
    p.feed(html_data)
    p.close()
    #    if not debug:
    return data



class ReadError(Exception):
    """This class defines a read error when it's impossible to read an url."""
    pass




# A little test suite
def test(args = None):
    import sys
    
    if not args:
        args = sys.argv[1:]
    
    if len(args) is 0:
        print 'COMMAND: url1 ...'
        print 'Provide all data text available in an html url.'
        sys.exit(1)
    
    for url in args:
        try:
            parse_html_url(url, debug=1)
        except ReadError:
            print 'read error'
            sys.exit(1)
        print '\n'



if __name__ == '__main__':
    test()
