Blame test/shaping/hb_test_tools.py

Packit Service 5bcba8
#!/usr/bin/env python
Packit Service 5bcba8
Packit Service 5bcba8
from __future__ import print_function
Packit Service 5bcba8
import sys, os, re, difflib, unicodedata, errno, cgi
Packit Service 5bcba8
from itertools import *
Packit Service 5bcba8
Packit Service 5bcba8
diff_symbols = "-+=*&^%$#@!~/"
Packit Service 5bcba8
diff_colors = ['red', 'green', 'blue']
Packit Service 5bcba8
Packit Service 5bcba8
try:
Packit Service 5bcba8
	unichr = unichr
Packit Service 5bcba8
Packit Service 5bcba8
	if sys.maxunicode < 0x10FFFF:
Packit Service 5bcba8
		# workarounds for Python 2 "narrow" builds with UCS2-only support.
Packit Service 5bcba8
Packit Service 5bcba8
		_narrow_unichr = unichr
Packit Service 5bcba8
Packit Service 5bcba8
		def unichr(i):
Packit Service 5bcba8
			"""
Packit Service 5bcba8
			Return the unicode character whose Unicode code is the integer 'i'.
Packit Service 5bcba8
			The valid range is 0 to 0x10FFFF inclusive.
Packit Service 5bcba8
Packit Service 5bcba8
			>>> _narrow_unichr(0xFFFF + 1)
Packit Service 5bcba8
			Traceback (most recent call last):
Packit Service 5bcba8
			  File "<stdin>", line 1, in ?
Packit Service 5bcba8
			ValueError: unichr() arg not in range(0x10000) (narrow Python build)
Packit Service 5bcba8
			>>> unichr(0xFFFF + 1) == u'\U00010000'
Packit Service 5bcba8
			True
Packit Service 5bcba8
			>>> unichr(1114111) == u'\U0010FFFF'
Packit Service 5bcba8
			True
Packit Service 5bcba8
			>>> unichr(0x10FFFF + 1)
Packit Service 5bcba8
			Traceback (most recent call last):
Packit Service 5bcba8
			  File "<stdin>", line 1, in ?
Packit Service 5bcba8
			ValueError: unichr() arg not in range(0x110000)
Packit Service 5bcba8
			"""
Packit Service 5bcba8
			try:
Packit Service 5bcba8
				return _narrow_unichr(i)
Packit Service 5bcba8
			except ValueError:
Packit Service 5bcba8
				try:
Packit Service 5bcba8
					padded_hex_str = hex(i)[2:].zfill(8)
Packit Service 5bcba8
					escape_str = "\\U" + padded_hex_str
Packit Service 5bcba8
					return escape_str.decode("unicode-escape")
Packit Service 5bcba8
				except UnicodeDecodeError:
Packit Service 5bcba8
					raise ValueError('unichr() arg not in range(0x110000)')
Packit Service 5bcba8
Packit Service 5bcba8
except NameError:
Packit Service 5bcba8
	unichr = chr
Packit Service 5bcba8
Packit Service 5bcba8
try:
Packit Service 5bcba8
	unicode = unicode
Packit Service 5bcba8
except NameError:
Packit Service 5bcba8
	unicode = str
Packit Service 5bcba8
Packit Service 5bcba8
def tounicode(s, encoding='ascii', errors='strict'):
Packit Service 5bcba8
	if not isinstance(s, unicode):
Packit Service 5bcba8
		return s.decode(encoding, errors)
Packit Service 5bcba8
	else:
Packit Service 5bcba8
		return s
Packit Service 5bcba8
Packit Service 5bcba8
class ColorFormatter:
Packit Service 5bcba8
Packit Service 5bcba8
	class Null:
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def start_color (c): return ''
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def end_color (): return ''
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def escape (s): return s
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def newline (): return '\n'
Packit Service 5bcba8
Packit Service 5bcba8
	class ANSI:
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def start_color (c):
Packit Service 5bcba8
			return {
Packit Service 5bcba8
				'red': '\033[41;37;1m',
Packit Service 5bcba8
				'green': '\033[42;37;1m',
Packit Service 5bcba8
				'blue': '\033[44;37;1m',
Packit Service 5bcba8
			}[c]
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def end_color ():
Packit Service 5bcba8
			return '\033[m'
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def escape (s): return s
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def newline (): return '\n'
Packit Service 5bcba8
Packit Service 5bcba8
	class HTML:
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def start_color (c):
Packit Service 5bcba8
			return '' % c
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def end_color ():
Packit Service 5bcba8
			return ''
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def escape (s): return cgi.escape (s)
Packit Service 5bcba8
		@staticmethod
Packit Service 5bcba8
		def newline (): return '
\n'
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def Auto (argv = [], out = sys.stdout):
Packit Service 5bcba8
		format = ColorFormatter.ANSI
Packit Service 5bcba8
		if "--format" in argv:
Packit Service 5bcba8
			argv.remove ("--format")
Packit Service 5bcba8
			format = ColorFormatter.ANSI
Packit Service 5bcba8
		if "--format=ansi" in argv:
Packit Service 5bcba8
			argv.remove ("--format=ansi")
Packit Service 5bcba8
			format = ColorFormatter.ANSI
Packit Service 5bcba8
		if "--format=html" in argv:
Packit Service 5bcba8
			argv.remove ("--format=html")
Packit Service 5bcba8
			format = ColorFormatter.HTML
Packit Service 5bcba8
		if "--no-format" in argv:
Packit Service 5bcba8
			argv.remove ("--no-format")
Packit Service 5bcba8
			format = ColorFormatter.Null
Packit Service 5bcba8
		return format
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class DiffColorizer:
Packit Service 5bcba8
Packit Service 5bcba8
	diff_regex = re.compile ('([a-za-z0-9_]*)([^a-za-z0-9_]?)')
Packit Service 5bcba8
Packit Service 5bcba8
	def __init__ (self, formatter, colors=diff_colors, symbols=diff_symbols):
Packit Service 5bcba8
		self.formatter = formatter
Packit Service 5bcba8
		self.colors = colors
Packit Service 5bcba8
		self.symbols = symbols
Packit Service 5bcba8
Packit Service 5bcba8
	def colorize_lines (self, lines):
Packit Service 5bcba8
		lines = (l if l else '' for l in lines)
Packit Service 5bcba8
		ss = [self.diff_regex.sub (r'\1\n\2\n', l).splitlines (True) for l in lines]
Packit Service 5bcba8
		oo = ["",""]
Packit Service 5bcba8
		st = [False, False]
Packit Service 5bcba8
		for l in difflib.Differ().compare (*ss):
Packit Service 5bcba8
			if l[0] == '?':
Packit Service 5bcba8
				continue
Packit Service 5bcba8
			if l[0] == ' ':
Packit Service 5bcba8
				for i in range(2):
Packit Service 5bcba8
					if st[i]:
Packit Service 5bcba8
						oo[i] += self.formatter.end_color ()
Packit Service 5bcba8
						st[i] = False
Packit Service 5bcba8
				oo = [o + self.formatter.escape (l[2:]) for o in oo]
Packit Service 5bcba8
				continue
Packit Service 5bcba8
			if l[0] in self.symbols:
Packit Service 5bcba8
				i = self.symbols.index (l[0])
Packit Service 5bcba8
				if not st[i]:
Packit Service 5bcba8
					oo[i] += self.formatter.start_color (self.colors[i])
Packit Service 5bcba8
					st[i] = True
Packit Service 5bcba8
				oo[i] += self.formatter.escape (l[2:])
Packit Service 5bcba8
				continue
Packit Service 5bcba8
		for i in range(2):
Packit Service 5bcba8
			if st[i]:
Packit Service 5bcba8
				oo[i] += self.formatter.end_color ()
Packit Service 5bcba8
				st[i] = False
Packit Service 5bcba8
		oo = [o.replace ('\n', '') for o in oo]
Packit Service 5bcba8
		return [s1+s2+self.formatter.newline () for (s1,s2) in zip (self.symbols, oo) if s2]
Packit Service 5bcba8
Packit Service 5bcba8
	def colorize_diff (self, f):
Packit Service 5bcba8
		lines = [None, None]
Packit Service 5bcba8
		for l in f:
Packit Service 5bcba8
			if l[0] not in self.symbols:
Packit Service 5bcba8
				yield self.formatter.escape (l).replace ('\n', self.formatter.newline ())
Packit Service 5bcba8
				continue
Packit Service 5bcba8
			i = self.symbols.index (l[0])
Packit Service 5bcba8
			if lines[i]:
Packit Service 5bcba8
				# Flush
Packit Service 5bcba8
				for line in self.colorize_lines (lines):
Packit Service 5bcba8
					yield line
Packit Service 5bcba8
				lines = [None, None]
Packit Service 5bcba8
			lines[i] = l[1:]
Packit Service 5bcba8
			if (all (lines)):
Packit Service 5bcba8
				# Flush
Packit Service 5bcba8
				for line in self.colorize_lines (lines):
Packit Service 5bcba8
					yield line
Packit Service 5bcba8
				lines = [None, None]
Packit Service 5bcba8
		if (any (lines)):
Packit Service 5bcba8
			# Flush
Packit Service 5bcba8
			for line in self.colorize_lines (lines):
Packit Service 5bcba8
				yield line
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class ZipDiffer:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def diff_files (files, symbols=diff_symbols):
Packit Service 5bcba8
		files = tuple (files) # in case it's a generator, copy it
Packit Service 5bcba8
		try:
Packit Service 5bcba8
			for lines in izip_longest (*files):
Packit Service 5bcba8
				if all (lines[0] == line for line in lines[1:]):
Packit Service 5bcba8
					sys.stdout.writelines ([" ", lines[0]])
Packit Service 5bcba8
					continue
Packit Service 5bcba8
Packit Service 5bcba8
				for i, l in enumerate (lines):
Packit Service 5bcba8
					if l:
Packit Service 5bcba8
						sys.stdout.writelines ([symbols[i], l])
Packit Service 5bcba8
		except IOError as e:
Packit Service 5bcba8
			if e.errno != errno.EPIPE:
Packit Service 5bcba8
				print ("%s: %s: %s" % (sys.argv[0], e.filename, e.strerror), file=sys.stderr)
Packit Service 5bcba8
				sys.exit (1)
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class DiffFilters:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def filter_failures (f):
Packit Service 5bcba8
		for key, lines in DiffHelpers.separate_test_cases (f):
Packit Service 5bcba8
			lines = list (lines)
Packit Service 5bcba8
			if not DiffHelpers.test_passed (lines):
Packit Service 5bcba8
				for l in lines: yield l
Packit Service 5bcba8
Packit Service 5bcba8
class Stat:
Packit Service 5bcba8
Packit Service 5bcba8
	def __init__ (self):
Packit Service 5bcba8
		self.count = 0
Packit Service 5bcba8
		self.freq = 0
Packit Service 5bcba8
Packit Service 5bcba8
	def add (self, test):
Packit Service 5bcba8
		self.count += 1
Packit Service 5bcba8
		self.freq += test.freq
Packit Service 5bcba8
Packit Service 5bcba8
class Stats:
Packit Service 5bcba8
Packit Service 5bcba8
	def __init__ (self):
Packit Service 5bcba8
		self.passed = Stat ()
Packit Service 5bcba8
		self.failed = Stat ()
Packit Service 5bcba8
		self.total  = Stat ()
Packit Service 5bcba8
Packit Service 5bcba8
	def add (self, test):
Packit Service 5bcba8
		self.total.add (test)
Packit Service 5bcba8
		if test.passed:
Packit Service 5bcba8
			self.passed.add (test)
Packit Service 5bcba8
		else:
Packit Service 5bcba8
			self.failed.add (test)
Packit Service 5bcba8
Packit Service 5bcba8
	def mean (self):
Packit Service 5bcba8
		return float (self.passed.count) / self.total.count
Packit Service 5bcba8
Packit Service 5bcba8
	def variance (self):
Packit Service 5bcba8
		return (float (self.passed.count) / self.total.count) * \
Packit Service 5bcba8
		       (float (self.failed.count) / self.total.count)
Packit Service 5bcba8
Packit Service 5bcba8
	def stddev (self):
Packit Service 5bcba8
		return self.variance () ** .5
Packit Service 5bcba8
Packit Service 5bcba8
	def zscore (self, population):
Packit Service 5bcba8
		"""Calculate the standard score.
Packit Service 5bcba8
		   Population is the Stats for population.
Packit Service 5bcba8
		   Self is Stats for sample.
Packit Service 5bcba8
		   Returns larger absolute value if sample is highly unlikely to be random.
Packit Service 5bcba8
		   Anything outside of -3..+3 is very unlikely to be random.
Packit Service 5bcba8
		   See: http://en.wikipedia.org/wiki/Standard_score"""
Packit Service 5bcba8
Packit Service 5bcba8
		return (self.mean () - population.mean ()) / population.stddev ()
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class DiffSinks:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def print_stat (f):
Packit Service 5bcba8
		passed = 0
Packit Service 5bcba8
		failed = 0
Packit Service 5bcba8
		# XXX port to Stats, but that would really slow us down here
Packit Service 5bcba8
		for key, lines in DiffHelpers.separate_test_cases (f):
Packit Service 5bcba8
			if DiffHelpers.test_passed (lines):
Packit Service 5bcba8
				passed += 1
Packit Service 5bcba8
			else:
Packit Service 5bcba8
				failed += 1
Packit Service 5bcba8
		total = passed + failed
Packit Service 5bcba8
		print ("%d out of %d tests passed.  %d failed (%g%%)" % (passed, total, failed, 100. * failed / total))
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def print_ngrams (f, ns=(1,2,3)):
Packit Service 5bcba8
		gens = tuple (Ngram.generator (n) for n in ns)
Packit Service 5bcba8
		allstats = Stats ()
Packit Service 5bcba8
		allgrams = {}
Packit Service 5bcba8
		for key, lines in DiffHelpers.separate_test_cases (f):
Packit Service 5bcba8
			test = Test (lines)
Packit Service 5bcba8
			allstats.add (test)
Packit Service 5bcba8
Packit Service 5bcba8
			for gen in gens:
Packit Service 5bcba8
				for ngram in gen (test.unicodes):
Packit Service 5bcba8
					if ngram not in allgrams:
Packit Service 5bcba8
						allgrams[ngram] = Stats ()
Packit Service 5bcba8
					allgrams[ngram].add (test)
Packit Service 5bcba8
Packit Service 5bcba8
		importantgrams = {}
Packit Service 5bcba8
		for ngram, stats in allgrams.iteritems ():
Packit Service 5bcba8
			if stats.failed.count >= 30: # for statistical reasons
Packit Service 5bcba8
				importantgrams[ngram] = stats
Packit Service 5bcba8
		allgrams = importantgrams
Packit Service 5bcba8
		del importantgrams
Packit Service 5bcba8
Packit Service 5bcba8
		for ngram, stats in allgrams.iteritems ():
Packit Service 5bcba8
			print ("zscore: %9f failed: %6d passed: %6d ngram: <%s>" % (stats.zscore (allstats), stats.failed.count, stats.passed.count, ','.join ("U+%04X" % u for u in ngram)))
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class Test:
Packit Service 5bcba8
Packit Service 5bcba8
	def __init__ (self, lines):
Packit Service 5bcba8
		self.freq = 1
Packit Service 5bcba8
		self.passed = True
Packit Service 5bcba8
		self.identifier = None
Packit Service 5bcba8
		self.text = None
Packit Service 5bcba8
		self.unicodes = None
Packit Service 5bcba8
		self.glyphs = None
Packit Service 5bcba8
		for l in lines:
Packit Service 5bcba8
			symbol = l[0]
Packit Service 5bcba8
			if symbol != ' ':
Packit Service 5bcba8
				self.passed = False
Packit Service 5bcba8
			i = 1
Packit Service 5bcba8
			if ':' in l:
Packit Service 5bcba8
				i = l.index (':')
Packit Service 5bcba8
				if not self.identifier:
Packit Service 5bcba8
					self.identifier = l[1:i]
Packit Service 5bcba8
				i = i + 2 # Skip colon and space
Packit Service 5bcba8
			j = -1
Packit Service 5bcba8
			if l[j] == '\n':
Packit Service 5bcba8
				j -= 1
Packit Service 5bcba8
			brackets = l[i] + l[j]
Packit Service 5bcba8
			l = l[i+1:-2]
Packit Service 5bcba8
			if brackets == '()':
Packit Service 5bcba8
				self.text = l
Packit Service 5bcba8
			elif brackets == '<>':
Packit Service 5bcba8
				self.unicodes = Unicode.parse (l)
Packit Service 5bcba8
			elif brackets == '[]':
Packit Service 5bcba8
				# XXX we don't handle failed tests here
Packit Service 5bcba8
				self.glyphs = l
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class DiffHelpers:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def separate_test_cases (f):
Packit Service 5bcba8
		'''Reads lines from f, and if the lines have identifiers, ie.
Packit Service 5bcba8
		   have a colon character, groups them by identifier,
Packit Service 5bcba8
		   yielding lists of all lines with the same identifier.'''
Packit Service 5bcba8
Packit Service 5bcba8
		def identifier (l):
Packit Service 5bcba8
			if ':' in l[1:]:
Packit Service 5bcba8
				return l[1:l.index (':')]
Packit Service 5bcba8
			return l
Packit Service 5bcba8
		return groupby (f, key=identifier)
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def test_passed (lines):
Packit Service 5bcba8
		lines = list (lines)
Packit Service 5bcba8
		# XXX This is a hack, but does the job for now.
Packit Service 5bcba8
		if any (l.find("space+0|space+0") >= 0 for l in lines if l[0] == '+'): return True
Packit Service 5bcba8
		if any (l.find("uni25CC") >= 0 for l in lines if l[0] == '+'): return True
Packit Service 5bcba8
		if any (l.find("dottedcircle") >= 0 for l in lines if l[0] == '+'): return True
Packit Service 5bcba8
		if any (l.find("glyph0") >= 0 for l in lines if l[0] == '+'): return True
Packit Service 5bcba8
		if any (l.find("gid0") >= 0 for l in lines if l[0] == '+'): return True
Packit Service 5bcba8
		if any (l.find("notdef") >= 0 for l in lines if l[0] == '+'): return True
Packit Service 5bcba8
		return all (l[0] == ' ' for l in lines)
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class FilterHelpers:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def filter_printer_function (filter_callback):
Packit Service 5bcba8
		def printer (f):
Packit Service 5bcba8
			for line in filter_callback (f):
Packit Service 5bcba8
				print (line)
Packit Service 5bcba8
		return printer
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def filter_printer_function_no_newline (filter_callback):
Packit Service 5bcba8
		def printer (f):
Packit Service 5bcba8
			for line in filter_callback (f):
Packit Service 5bcba8
				sys.stdout.writelines ([line])
Packit Service 5bcba8
		return printer
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class Ngram:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def generator (n):
Packit Service 5bcba8
Packit Service 5bcba8
		def gen (f):
Packit Service 5bcba8
			l = []
Packit Service 5bcba8
			for x in f:
Packit Service 5bcba8
				l.append (x)
Packit Service 5bcba8
				if len (l) == n:
Packit Service 5bcba8
					yield tuple (l)
Packit Service 5bcba8
					l[:1] = []
Packit Service 5bcba8
Packit Service 5bcba8
		gen.n = n
Packit Service 5bcba8
		return gen
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class UtilMains:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def process_multiple_files (callback, mnemonic = "FILE"):
Packit Service 5bcba8
Packit Service 5bcba8
		if "--help" in sys.argv:
Packit Service 5bcba8
			print ("Usage: %s %s..." % (sys.argv[0], mnemonic))
Packit Service 5bcba8
			sys.exit (1)
Packit Service 5bcba8
Packit Service 5bcba8
		try:
Packit Service 5bcba8
			files = sys.argv[1:] if len (sys.argv) > 1 else ['-']
Packit Service 5bcba8
			for s in files:
Packit Service 5bcba8
				callback (FileHelpers.open_file_or_stdin (s))
Packit Service 5bcba8
		except IOError as e:
Packit Service 5bcba8
			if e.errno != errno.EPIPE:
Packit Service 5bcba8
				print ("%s: %s: %s" % (sys.argv[0], e.filename, e.strerror), file=sys.stderr)
Packit Service 5bcba8
				sys.exit (1)
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def process_multiple_args (callback, mnemonic):
Packit Service 5bcba8
Packit Service 5bcba8
		if len (sys.argv) == 1 or "--help" in sys.argv:
Packit Service 5bcba8
			print ("Usage: %s %s..." % (sys.argv[0], mnemonic))
Packit Service 5bcba8
			sys.exit (1)
Packit Service 5bcba8
Packit Service 5bcba8
		try:
Packit Service 5bcba8
			for s in sys.argv[1:]:
Packit Service 5bcba8
				callback (s)
Packit Service 5bcba8
		except IOError as e:
Packit Service 5bcba8
			if e.errno != errno.EPIPE:
Packit Service 5bcba8
				print ("%s: %s: %s" % (sys.argv[0], e.filename, e.strerror), file=sys.stderr)
Packit Service 5bcba8
				sys.exit (1)
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def filter_multiple_strings_or_stdin (callback, mnemonic, \
Packit Service 5bcba8
					      separator = " ", \
Packit Service 5bcba8
					      concat_separator = False):
Packit Service 5bcba8
Packit Service 5bcba8
		if "--help" in sys.argv:
Packit Service 5bcba8
			print ("Usage:\n  %s %s...\nor:\n  %s\n\nWhen called with no arguments, input is read from standard input." \
Packit Service 5bcba8
			      % (sys.argv[0], mnemonic, sys.argv[0]))
Packit Service 5bcba8
			sys.exit (1)
Packit Service 5bcba8
Packit Service 5bcba8
		try:
Packit Service 5bcba8
			if len (sys.argv) == 1:
Packit Service 5bcba8
				while (1):
Packit Service 5bcba8
					line = sys.stdin.readline ()
Packit Service 5bcba8
					if not len (line):
Packit Service 5bcba8
						break
Packit Service 5bcba8
					if line[-1] == '\n':
Packit Service 5bcba8
						line = line[:-1]
Packit Service 5bcba8
					print (callback (line))
Packit Service 5bcba8
			else:
Packit Service 5bcba8
				args = sys.argv[1:]
Packit Service 5bcba8
				if concat_separator != False:
Packit Service 5bcba8
					args = [concat_separator.join (args)]
Packit Service 5bcba8
				print (separator.join (callback (x) for x in (args)))
Packit Service 5bcba8
		except IOError as e:
Packit Service 5bcba8
			if e.errno != errno.EPIPE:
Packit Service 5bcba8
				print ("%s: %s: %s" % (sys.argv[0], e.filename, e.strerror), file=sys.stderr)
Packit Service 5bcba8
				sys.exit (1)
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class Unicode:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def decode (s):
Packit Service 5bcba8
		return u','.join ("U+%04X" % ord (u) for u in tounicode (s, 'utf-8'))
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def parse (s):
Packit Service 5bcba8
		s = re.sub (r"0[xX]", " ", s)
Packit Service 5bcba8
		s = re.sub (r"[<+>{},;&#\\xXuUnNiI\n	]", " ", s)
Packit Service 5bcba8
		return [int (x, 16) for x in s.split ()]
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def encode (s):
Packit Service 5bcba8
		s = u''.join (unichr (x) for x in Unicode.parse (s))
Packit Service 5bcba8
		if sys.version_info[0] == 2: s = s.encode ('utf-8')
Packit Service 5bcba8
		return s
Packit Service 5bcba8
Packit Service 5bcba8
	shorthands = {
Packit Service 5bcba8
		"ZERO WIDTH NON-JOINER": "ZWNJ",
Packit Service 5bcba8
		"ZERO WIDTH JOINER": "ZWJ",
Packit Service 5bcba8
		"NARROW NO-BREAK SPACE": "NNBSP",
Packit Service 5bcba8
		"COMBINING GRAPHEME JOINER": "CGJ",
Packit Service 5bcba8
		"LEFT-TO-RIGHT MARK": "LRM",
Packit Service 5bcba8
		"RIGHT-TO-LEFT MARK": "RLM",
Packit Service 5bcba8
		"LEFT-TO-RIGHT EMBEDDING": "LRE",
Packit Service 5bcba8
		"RIGHT-TO-LEFT EMBEDDING": "RLE",
Packit Service 5bcba8
		"POP DIRECTIONAL FORMATTING": "PDF",
Packit Service 5bcba8
		"LEFT-TO-RIGHT OVERRIDE": "LRO",
Packit Service 5bcba8
		"RIGHT-TO-LEFT OVERRIDE": "RLO",
Packit Service 5bcba8
	}
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def pretty_name (u):
Packit Service 5bcba8
		try:
Packit Service 5bcba8
			s = unicodedata.name (u)
Packit Service 5bcba8
		except ValueError:
Packit Service 5bcba8
			return "XXX"
Packit Service 5bcba8
		s = re.sub (".* LETTER ", "", s)
Packit Service 5bcba8
		s = re.sub (".* VOWEL SIGN (.*)", r"\1-MATRA", s)
Packit Service 5bcba8
		s = re.sub (".* SIGN ", "", s)
Packit Service 5bcba8
		s = re.sub (".* COMBINING ", "", s)
Packit Service 5bcba8
		if re.match (".* VIRAMA", s):
Packit Service 5bcba8
			s = "HALANT"
Packit Service 5bcba8
		if s in Unicode.shorthands:
Packit Service 5bcba8
			s = Unicode.shorthands[s]
Packit Service 5bcba8
		return s
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def pretty_names (s):
Packit Service 5bcba8
		s = re.sub (r"[<+>\\uU]", " ", s)
Packit Service 5bcba8
		s = re.sub (r"0[xX]", " ", s)
Packit Service 5bcba8
		s = [unichr (int (x, 16)) for x in re.split ('[, \n]', s) if len (x)]
Packit Service 5bcba8
		return u' + '.join (Unicode.pretty_name (x) for x in s).encode ('utf-8')
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class FileHelpers:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def open_file_or_stdin (f):
Packit Service 5bcba8
		if f == '-':
Packit Service 5bcba8
			return sys.stdin
Packit Service 5bcba8
		return file (f)
Packit Service 5bcba8
Packit Service 5bcba8
Packit Service 5bcba8
class Manifest:
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def read (s, strict = True):
Packit Service 5bcba8
Packit Service 5bcba8
		if not os.path.exists (s):
Packit Service 5bcba8
			if strict:
Packit Service 5bcba8
				print ("%s: %s does not exist" % (sys.argv[0], s), file=sys.stderr)
Packit Service 5bcba8
				sys.exit (1)
Packit Service 5bcba8
			return
Packit Service 5bcba8
Packit Service 5bcba8
		s = os.path.normpath (s)
Packit Service 5bcba8
Packit Service 5bcba8
		if os.path.isdir (s):
Packit Service 5bcba8
Packit Service 5bcba8
			try:
Packit Service 5bcba8
				m = file (os.path.join (s, "MANIFEST"))
Packit Service 5bcba8
				items = [x.strip () for x in m.readlines ()]
Packit Service 5bcba8
				for f in items:
Packit Service 5bcba8
					for p in Manifest.read (os.path.join (s, f)):
Packit Service 5bcba8
						yield p
Packit Service 5bcba8
			except IOError:
Packit Service 5bcba8
				if strict:
Packit Service 5bcba8
					print ("%s: %s does not exist" % (sys.argv[0], os.path.join (s, "MANIFEST")), file=sys.stderr)
Packit Service 5bcba8
					sys.exit (1)
Packit Service 5bcba8
				return
Packit Service 5bcba8
		else:
Packit Service 5bcba8
			yield s
Packit Service 5bcba8
Packit Service 5bcba8
	@staticmethod
Packit Service 5bcba8
	def update_recursive (s):
Packit Service 5bcba8
Packit Service 5bcba8
		for dirpath, dirnames, filenames in os.walk (s, followlinks=True):
Packit Service 5bcba8
Packit Service 5bcba8
			for f in ["MANIFEST", "README", "LICENSE", "COPYING", "AUTHORS", "SOURCES", "ChangeLog"]:
Packit Service 5bcba8
				if f in dirnames:
Packit Service 5bcba8
					dirnames.remove (f)
Packit Service 5bcba8
				if f in filenames:
Packit Service 5bcba8
					filenames.remove (f)
Packit Service 5bcba8
			dirnames.sort ()
Packit Service 5bcba8
			filenames.sort ()
Packit Service 5bcba8
			ms = os.path.join (dirpath, "MANIFEST")
Packit Service 5bcba8
			print ("  GEN    %s" % ms)
Packit Service 5bcba8
			m = open (ms, "w")
Packit Service 5bcba8
			for f in filenames:
Packit Service 5bcba8
				print (f, file=m)
Packit Service 5bcba8
			for f in dirnames:
Packit Service 5bcba8
				print (f, file=m)
Packit Service 5bcba8
			for f in dirnames:
Packit Service 5bcba8
				Manifest.update_recursive (os.path.join (dirpath, f))
Packit Service 5bcba8
Packit Service 5bcba8
if __name__ == '__main__':
Packit Service 5bcba8
	pass