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("&", "&")
data = data.replace(">", ">")
data = data.replace("<", "<")
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
|