#!/usr/bin/python
"""
$Id: tables.py,v 1.8 2007/04/26 07:26:49 dom Exp $

The TableTestCase implements the validator.testcase.TestCase
interface for the tests related to the following BPs:
* Do not use tables unless the client is known to support them
* Do not use nested tables.
* Do not use tables for layout.


License
-------
Copyright (c) 2006 World Wide Web Consortium, (Massachusetts
Institute of Technology, European Research Consortium for Informatics
and Mathematics, Keio University). All Rights Reserved. This work is
distributed under the W3C Software License [1] 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.

[1] http://www.w3.org/Consortium/Legal/copyright-software

"""


from  validator import testcase 

# Tests regarding the TABLES_SUPPORT, TABLES_NESTED, TABLES_LAYOUT BP
class TablesTestCase(testcase.LinksBasedTestCase):
    BpId = ["TABLES_SUPPORT","TABLES_NESTED","TABLES_LAYOUT"]

    def startDocument(self):
        self._nestedTable = 0
        self._numberOfLines = 0
        self._numberOfColumns = 0
        self._maxNumberOfColumns = 0
        self._inCell = False
        self._cellContent = ""
        self._tableLayout = False
        testcase.LinksBasedTestCase.startDocument(self)        

            
    def startElement(self, name, attrs):
        if self._inCell and name=="img"  and attrs.has_key("src"):
            location = testcase.LineColumnLocation(self.uri,self.getEncoding(),self.locator.getLineNumber(),self.locator.getColumnNumber())
            target = self._absolutize(attrs['src'])
            headers,content = self._http_request(target)
            try:
                image = Image.open(cStringIO.StringIO(content))
            except IOError("cannot identify image file"):
                self.addObservation(testcase.Observation("IG7",location))
            width,height = image.size
            # very small graphic in a table, implies a breech of TABLES_LAYOUT
            if width<=2 and height<=2:
                self.addObservation(testcase.Observation("TA6",location))
             
        elif name=="table":
            location = testcase.LineColumnLocation(self.uri,self.getEncoding(),self.locator.getLineNumber(),self.locator.getColumnNumber())
            # we log a warning re TABLES_SUPPORT
            self.addObservation(testcase.Observation("TA1",location))
            self._numberOfLines = 0
            self._nestedTable = self._nestedTable + 1
            if self._nestedTable > 1:
                self.addObservation(testcase.Observation("TA2",location))
        elif name=="tr":
            self._numberOfLines = self._numberOfLines + 1
            self._maxNumberOfColumns = max(self._maxNumberOfColumns,self._numberOfColumns)
            self._numberOfColumns = 0
        elif name=="td" or name=="th":
            self._numberOfColumns = self._numberOfColumns + 1
            self._inCell = True
            self._cellContent = ""

    def characters(self,content):
        if self._inCell:
            self._cellContent = self._cellContent + content

    def endElement(self,name):
        if name=="table":
            self._nestedTable = self._nestedTable - 1
            location = testcase.LineColumnLocation(self.uri,self.getEncoding(),self.locator.getLineNumber(),self.locator.getColumnNumber())
            if self._numberOfLines == 1:
                # single rows tables fails tables_layout
                self.addObservation(testcase.Observation("TA3",location))
            if self._maxNumberOfColumns < 2:
                # single columns tables fails tables_layout
                self.addObservation(testcase.Observation("TA5",location))
        elif name=="td" or name=="th":
            self._inCell = False

    def endDocument(self):
        if not "TA1" in self._observations:
            self.addObservation(testcase.Observation("TA4",testcase.Location(self.uri)))



# -------------------------
# Unit tests for this module
import unittest

from validator.testcase import TestResults, Observation, Location, LineColumnLocation
class Tests(unittest.TestCase):
    def _test(self,inp,res):
        a = TablesTestCase()
        self.assertEqual(a.run(inp),res)
        
    def testWithNoTables(self):
        inp = "http://dev.w3.org/cvsweb/~checkout~/2006/mwbp-validator/tests/base.xhtml"
        res = TestResults(
            [Observation("TA4",Location(inp))]
            )
        self._test(inp,res)

    def testWithOneTable(self):
        inp = "http://dev.w3.org/cvsweb/~checkout~/2006/mwbp-validator/tests/tables-1.xhtml"
        res = TestResults(
            [Observation("TA1",LineColumnLocation(inp,'utf-8',13,0))])
        self._test(inp,res)

    def testWithNestedTables(self):
        inp = "http://dev.w3.org/cvsweb/~checkout~/2006/mwbp-validator/tests/tables-2.xhtml"
        res = TestResults(
            [Observation('TA1',LineColumnLocation(inp,'utf-8',13,0)),
             Observation('TA1',LineColumnLocation(inp,'utf-8',14,8)),
             Observation("TA2",LineColumnLocation(inp,'utf-8',14,8)),
             Observation("TA5",LineColumnLocation(inp,'utf-8',14,121)),
             Observation("TA5",LineColumnLocation(inp,'utf-8',16,0))])
        self._test(inp,res)


    def testWithASingleRowTable(self):
        inp = "http://dev.w3.org/cvsweb/~checkout~/2006/mwbp-validator/tests/tables-3.xhtml"
        res = TestResults(
            [Observation('TA1',LineColumnLocation(inp,'utf-8',13,0)),
             Observation("TA3",LineColumnLocation(inp,'utf-8',19,0)),
             Observation('TA5',LineColumnLocation(inp,'utf-8',19,0))])
        self._test(inp,res)


def _test():
    unittest.main()

if __name__ == '__main__':
    _test()



