summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/tools/w3ctestlib/Utils.py
blob: 065c30491c7aaac938860775d0e949b2ac02d33c (plain)
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/python
# CSS Test Suite Manipulation Library Utilities
# Initial code by fantasai, joint copyright 2010 W3C and Microsoft
# Licensed under BSD 3-Clause: <http://www.w3.org/Consortium/Legal/2008/03-bsd-license>

###### XML Parsing ######

import os
import w3ctestlib
os.environ['XML_CATALOG_FILES'] = os.path.join(w3ctestlib.__path__[0], 'catalog/catalog.xml')

###### File path manipulation ######

import os.path
from os.path import sep, pardir

def assetName(path):
  return intern(os.path.splitext(os.path.basename(path))[0].lower().encode('ascii'))
  
def basepath(path):
  """ Returns the path part of os.path.split.
  """
  return os.path.dirname(path)

def isPathInsideBase(path, base=''):
  path = os.path.normpath(path)
  if base:
    base = os.path.normpath(base)
    pathlist = path.split(os.path.sep)
    baselist = base.split(os.path.sep)
    while baselist:
      p = pathlist.pop(0)
      b = baselist.pop(0)
      if p != b:
        return False
    return not pathlist[0].startswith(os.path.pardir)
  return not path.startswith(os.path.pardir)

def relpath(path, start):
  """Return relative path from start to end. WARNING: this is not the
     same as a relative URL; see relativeURL()."""
  try:
    return os.path.relpath(path, start)
  except AttributeError:
    # This function is copied directly from the Python 2.6 source
    # code, and is therefore under a different license.

    if not path:
        raise ValueError("no path specified")
    start_list = os.path.abspath(start).split(sep)
    path_list = os.path.abspath(path).split(sep)
    if start_list[0].lower() != path_list[0].lower():
        unc_path, rest = os.path.splitunc(path)
        unc_start, rest = os.path.splitunc(start)
        if bool(unc_path) ^ bool(unc_start):
            raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
                                                                % (path, start))
        else:
            raise ValueError("path is on drive %s, start on drive %s"
                                                % (path_list[0], start_list[0]))
    # Work out how much of the filepath is shared by start and path.
    for i in range(min(len(start_list), len(path_list))):
        if start_list[i].lower() != path_list[i].lower():
            break
    else:
        i += 1

    rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
    if not rel_list:
        return os.path.curdir
    return os.path.join(*rel_list)

def relativeURL(start, end):
  """ Returns relative URL from `start` to `end`.
  """
#  if isPathInsideBase(end, start):
#    return relpath(end, start)
#  else:
  return relpath(end, basepath(start))

def listfiles(path, ext = None):
  """ Returns a list of all files in a directory.
      Optionally lists only files with a given extension.
  """
  try:
    _,_,files = os.walk(path).next()
    if (ext):
      files = [fileName for fileName in files if fileName.endswith(ext)]
  except StopIteration:
    files = []
  return files

def listdirs(path):
  """ Returns a list of all subdirectories in a directory.
  """
  try:
    _,dirs,_ = os.walk(path).next()
  except StopIteration:
    dirs = []
  return dirs

###### MIME types and file extensions ######

extensionMap = { None     : 'application/octet-stream', # default
                 '.xht'   : 'application/xhtml+xml',
                 '.xhtml' : 'application/xhtml+xml',
                 '.xml'   : 'application/xml',
                 '.htm'   : 'text/html',
                 '.html'  : 'text/html',
                 '.txt'   : 'text/plain',
                 '.jpg'   : 'image/jpeg',
                 '.png'   : 'image/png',
                 '.svg'   : 'image/svg+xml',
               }

def getMimeFromExt(filepath):
  """Convenience function: equal to extenionMap.get(ext, extensionMap[None]).
  """
  if filepath.endswith('.htaccess'):
    return 'config/htaccess'
  ext = os.path.splitext(filepath)[1]
  return extensionMap.get(ext, extensionMap[None])

###### Escaping ######

import types
from htmlentitydefs import entitydefs

entityify = dict([c,e] for e,c in entitydefs.iteritems())

def escapeMarkup(data):
  """Escape markup characters (&, >, <). Copied from xml.sax.saxutils.
  """
  # must do ampersand first
  data = data.replace("&", "&amp;")
  data = data.replace(">", "&gt;")
  data = data.replace("<", "&lt;")
  return data

def escapeToNamedASCII(text):
  """Escapes to named entities where possible and numeric-escapes non-ASCII
  """
  return escapeToNamed(text).encode('ascii', 'xmlcharrefreplace')

def escapeToNamed(text):
  """Escape characters with named entities.
  """
  escapable = set()

  for c in text:
    if ord(c) > 127:
      escapable.add(c)
  if type(text) == types.UnicodeType:
    for c in escapable:
      cLatin = c.encode('Latin-1', 'ignore')
      if (cLatin in entityify):
        text = text.replace(c, "&%s;" % entityify[cLatin])
  else:
    for c in escapable:
      text = text.replace(c, "&%s;" % entityify[c])
  return text