mirror of
https://github.com/servo/servo.git
synced 2025-06-24 17:14:33 +01:00
161 lines
4.9 KiB
Python
161 lines
4.9 KiB
Python
#!/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
|