Package: python-empy Version: 3.3-7 Followup-For: Bug #732101 Arg, you are right. I did not include in the patch the files in the git stagging area. Thanks for the reminder Ana. Here goes again:
diff --git a/debian/patches/support_python3.patch b/debian/patches/support_python3.patch new file mode 100644 index 0000000..ac368ad --- /dev/null +++ b/debian/patches/support_python3.patch @@ -0,0 +1,1164 @@ +--- a/em.py ++++ b/em.py +@@ -17,22 +17,16 @@ + + import copy + import getopt ++import inspect + import os + import re +-import string + import sys + import types + + try: +- # The equivalent of import cStringIO as StringIO. +- import cStringIO +- StringIO = cStringIO +- del cStringIO ++ from cStringIO import StringIO + except ImportError: +- import StringIO +- +-# For backward compatibility, we can't assume these are defined. +-False, True = 0, 1 ++ from io import StringIO + + # Some basic defaults. + FAILURE_CODE = 1 +@@ -298,9 +292,9 @@ + self.exc = exc + + def __str__(self): +- backtrace = map(lambda x: str(x), self.contexts) ++ backtrace = [str(x) for x in self.contexts] + return "%s: %s (%s)" % (self.exc.__class__, self.exc, \ +- (string.join(backtrace, ', '))) ++ (', '.join(backtrace))) + + + class Subsystem: +@@ -318,10 +312,10 @@ + inputErrors=None, outputErrors=None): + self.useUnicode = True + try: +- unicode ++ str + import codecs + except (NameError, ImportError): +- raise SubsystemError, "Unicode subsystem unavailable" ++ raise SubsystemError("Unicode subsystem unavailable") + defaultEncoding = sys.getdefaultencoding() + if inputEncoding is None: + inputEncoding = defaultEncoding +@@ -338,7 +332,7 @@ + + def assertUnicode(self): + if not self.useUnicode: +- raise SubsystemError, "Unicode subsystem unavailable" ++ raise SubsystemError("Unicode subsystem unavailable") + + def open(self, name, mode=None): + if self.useUnicode: +@@ -381,14 +375,14 @@ + try: + return self.data[-1] + except IndexError: +- raise StackUnderflowError, "stack is empty for top" ++ raise StackUnderflowError("stack is empty for top") + + def pop(self): + """Pop the top element off the stack and return it.""" + try: + return self.data.pop() + except IndexError: +- raise StackUnderflowError, "stack is empty for pop" ++ raise StackUnderflowError("stack is empty for pop") + + def push(self, object): + """Push an element onto the top of the stack.""" +@@ -396,7 +390,7 @@ + + def filter(self, function): + """Filter the elements of the stack through the function.""" +- self.data = filter(function, self.data) ++ self.data = list(filter(function, self.data)) + + def purge(self): + """Purge the stack.""" +@@ -406,14 +400,14 @@ + """Create a duplicate of this stack.""" + return self.__class__(self.data[:]) + +- def __nonzero__(self): return len(self.data) != 0 ++ def __bool__(self): return len(self.data) != 0 + def __len__(self): return len(self.data) + def __getitem__(self, index): return self.data[-(index + 1)] + + def __repr__(self): + return '<%s instance at 0x%x [%s]>' % \ + (self.__class__, id(self), \ +- string.join(map(repr, self.data), ', ')) ++ ', '.join(list(map(repr, self.data)))) + + + class AbstractFile: +@@ -430,7 +424,7 @@ + self.mode = mode + self.buffered = buffered + if buffered: +- self.bufferFile = StringIO.StringIO() ++ self.bufferFile = StringIO() + else: + self.bufferFile = theSubsystem.open(filename, mode) + # Okay, we got this far, so the AbstractFile is initialized. +@@ -478,7 +472,7 @@ + strings or (readable) file objects.""" + + def __init__(self): +- self.file = StringIO.StringIO() ++ self.file = StringIO() + + # These methods define the writable file-like interface for the + # diversion. +@@ -504,7 +498,7 @@ + + def asFile(self): + """Return the diversion as a file.""" +- return StringIO.StringIO(self.file.getvalue()) ++ return StringIO(self.file.getvalue()) + + + class Stream: +@@ -544,15 +538,16 @@ + independently.""" + if shortcut == 0: + return NullFilter() +- elif type(shortcut) is types.FunctionType or \ +- type(shortcut) is types.BuiltinFunctionType or \ +- type(shortcut) is types.BuiltinMethodType or \ +- type(shortcut) is types.LambdaType: ++ elif isinstance(shortcut, types.FunctionType) or \ ++ inspect.ismethoddescriptor(shortcut) or \ ++ isinstance(shortcut, types.BuiltinFunctionType) or \ ++ isinstance(shortcut, types.BuiltinMethodType) or \ ++ isinstance(shortcut, types.LambdaType): + return FunctionFilter(shortcut) +- elif type(shortcut) is types.StringType: ++ elif isinstance(shortcut, bytes): + return StringFilter(filter) +- elif type(shortcut) is types.DictType: +- raise NotImplementedError, "mapping filters not yet supported" ++ elif isinstance(shortcut, dict): ++ raise NotImplementedError("mapping filters not yet supported") + else: + # Presume it's a plain old filter. + return shortcut +@@ -565,7 +560,7 @@ + thisFilter, lastFilter = self.filter, None + while thisFilter is not None and thisFilter is not self.file: + lastFilter = thisFilter +- thisFilter = thisFilter.next() ++ thisFilter = thisFilter.__next__() + return lastFilter + + def install(self, shortcut=None): +@@ -577,7 +572,7 @@ + # Shortcuts for "no filter." + self.filter = self.file + else: +- if type(shortcut) in (types.ListType, types.TupleType): ++ if type(shortcut) in (list, tuple): + shortcuts = list(shortcut) + else: + shortcuts = [shortcut] +@@ -626,43 +621,43 @@ + """Create a diversion if one does not already exist, but do not + divert to it yet.""" + if name is None: +- raise DiversionError, "diversion name must be non-None" +- if not self.diversions.has_key(name): ++ raise DiversionError("diversion name must be non-None") ++ if name not in self.diversions: + self.diversions[name] = Diversion() + + def retrieve(self, name): + """Retrieve the given diversion.""" + if name is None: +- raise DiversionError, "diversion name must be non-None" +- if self.diversions.has_key(name): ++ raise DiversionError("diversion name must be non-None") ++ if name in self.diversions: + return self.diversions[name] + else: +- raise DiversionError, "nonexistent diversion: %s" % name ++ raise DiversionError("nonexistent diversion: %s" % name) + + def divert(self, name): + """Start diverting.""" + if name is None: +- raise DiversionError, "diversion name must be non-None" ++ raise DiversionError("diversion name must be non-None") + self.create(name) + self.currentDiversion = name + + def undivert(self, name, purgeAfterwards=False): + """Undivert a particular diversion.""" + if name is None: +- raise DiversionError, "diversion name must be non-None" +- if self.diversions.has_key(name): ++ raise DiversionError("diversion name must be non-None") ++ if name in self.diversions: + diversion = self.diversions[name] + self.filter.write(diversion.asString()) + if purgeAfterwards: + self.purge(name) + else: +- raise DiversionError, "nonexistent diversion: %s" % name ++ raise DiversionError("nonexistent diversion: %s" % name) + + def purge(self, name): + """Purge the specified diversion.""" + if name is None: +- raise DiversionError, "diversion name must be non-None" +- if self.diversions.has_key(name): ++ raise DiversionError("diversion name must be non-None") ++ if name in self.diversions: + del self.diversions[name] + if self.currentDiversion == name: + self.currentDiversion = None +@@ -671,8 +666,7 @@ + """Undivert all pending diversions.""" + if self.diversions: + self.revert() # revert before undiverting! +- names = self.diversions.keys() +- names.sort() ++ names = sorted(list(self.diversions.keys())) + for name in names: + self.undivert(name) + if purgeAfterwards: +@@ -775,7 +769,7 @@ + raise NotImplementedError + self.sink = None + +- def next(self): ++ def __next__(self): + """Return the next filter/file-like object in the sequence, or None.""" + return self.sink + +@@ -821,7 +815,7 @@ + this, last = self, self + while this is not None: + last = this +- this = this.next() ++ this = this.__next__() + return last + + class NullFilter(Filter): +@@ -848,13 +842,13 @@ + filters any incoming data through it.""" + + def __init__(self, table): +- if not (type(table) == types.StringType and len(table) == 256): +- raise FilterError, "table must be 256-character string" ++ if not (isinstance(table, bytes) and len(table) == 256): ++ raise FilterError("table must be 256-character string") + Filter.__init__(self) + self.table = table + + def write(self, data): +- self.sink.write(string.translate(data, self.table)) ++ self.sink.write(data.translate(self.table)) + + class BufferedFilter(Filter): + +@@ -901,7 +895,7 @@ + + def write(self, data): + BufferedFilter.write(self, data) +- chunks = string.split(self.buffer, '\n') ++ chunks = self.buffer.split('\n') + for chunk in chunks[:-1]: + self.sink.write(chunk + '\n') + self.buffer = chunks[-1] +@@ -963,7 +957,7 @@ + + def deregister(self, interpreter): + if interpreter is not self.interpreter: +- raise Error, "hook not associated with this interpreter" ++ raise Error("hook not associated with this interpreter") + self.interpreter = None + + def push(self): +@@ -1133,7 +1127,7 @@ + if loc >= 0: + self.comment = scanner.chop(loc, 1) + else: +- raise TransientParseError, "comment expects newline" ++ raise TransientParseError("comment expects newline") + + def string(self): + return '%s#%s\n' % (self.prefix, self.comment) +@@ -1143,9 +1137,9 @@ + def scan(self, scanner): + loc = scanner.find('\n') + if loc >= 0: +- self.name = string.strip(scanner.chop(loc, 1)) ++ self.name = scanner.chop(loc, 1).strip() + else: +- raise TransientParseError, "context name expects newline" ++ raise TransientParseError("context name expects newline") + + def run(self, interpreter, locals): + context = interpreter.context() +@@ -1159,9 +1153,9 @@ + try: + self.line = int(scanner.chop(loc, 1)) + except ValueError: +- raise ParseError, "context line requires integer" ++ raise ParseError("context line requires integer") + else: +- raise TransientParseError, "context line expects newline" ++ raise TransientParseError("context line expects newline") + + def run(self, interpreter, locals): + context = interpreter.context() +@@ -1184,7 +1178,7 @@ + result = '\x08' + elif code == 'd': # decimal code + decimalCode = scanner.chop(3) +- result = chr(string.atoi(decimalCode, 10)) ++ result = chr(int(decimalCode, 10)) + elif code == 'e': # ESC + result = '\x1b' + elif code == 'f': # FF +@@ -1197,20 +1191,19 @@ + theSubsystem.assertUnicode() + import unicodedata + if scanner.chop(1) != '{': +- raise ParseError, r"Unicode name escape should be \N{...}" ++ raise ParseError(r"Unicode name escape should be \N{...}") + i = scanner.find('}') + name = scanner.chop(i, 1) + try: + result = unicodedata.lookup(name) + except KeyError: +- raise SubsystemError, \ +- "unknown Unicode character name: %s" % name ++ raise SubsystemError("unknown Unicode character name: %s" % name) + elif code == 'o': # octal code + octalCode = scanner.chop(3) +- result = chr(string.atoi(octalCode, 8)) ++ result = chr(int(octalCode, 8)) + elif code == 'q': # quaternary code + quaternaryCode = scanner.chop(4) +- result = chr(string.atoi(quaternaryCode, 4)) ++ result = chr(int(quaternaryCode, 4)) + elif code == 'r': # CR + result = '\x0d' + elif code in 's ': # SP +@@ -1220,32 +1213,32 @@ + elif code in 'u': # Unicode 16-bit hex literal + theSubsystem.assertUnicode() + hexCode = scanner.chop(4) +- result = unichr(string.atoi(hexCode, 16)) ++ result = chr(int(hexCode, 16)) + elif code in 'U': # Unicode 32-bit hex literal + theSubsystem.assertUnicode() + hexCode = scanner.chop(8) +- result = unichr(string.atoi(hexCode, 16)) ++ result = chr(int(hexCode, 16)) + elif code == 'v': # VT + result = '\x0b' + elif code == 'x': # hexadecimal code + hexCode = scanner.chop(2) +- result = chr(string.atoi(hexCode, 16)) ++ result = chr(int(hexCode, 16)) + elif code == 'z': # EOT + result = '\x04' + elif code == '^': # control character +- controlCode = string.upper(scanner.chop(1)) ++ controlCode = scanner.chop(1).upper() + if controlCode >= '@' and controlCode <= '`': + result = chr(ord(controlCode) - ord('@')) + elif controlCode == '?': + result = '\x7f' + else: +- raise ParseError, "invalid escape control code" ++ raise ParseError("invalid escape control code") + else: +- raise ParseError, "unrecognized escape code" ++ raise ParseError("unrecognized escape code") + assert result is not None + self.code = result + except ValueError: +- raise ParseError, "invalid numeric escape code" ++ raise ParseError("invalid numeric escape code") + + def run(self, interpreter, locals): + interpreter.write(self.code) +@@ -1260,13 +1253,13 @@ + if loc >= 0: + line = scanner.chop(loc, 1) + if not line: +- raise ParseError, "significator must have nonblank key" ++ raise ParseError("significator must have nonblank key") + if line[0] in ' \t\v\n': +- raise ParseError, "no whitespace between % and key" ++ raise ParseError("no whitespace between % and key") + # Work around a subtle CPython-Jython difference by stripping + # the string before splitting it: 'a '.split(None, 1) has two + # elements in Jython 2.1). +- fields = string.split(string.strip(line), None, 1) ++ fields = line.strip().split(None, 1) + if len(fields) == 2 and fields[1] == '': + fields.pop() + self.key = fields[0] +@@ -1274,12 +1267,12 @@ + fields.append(None) + self.key, self.valueCode = fields + else: +- raise TransientParseError, "significator expects newline" ++ raise TransientParseError("significator expects newline") + + def run(self, interpreter, locals): + value = self.valueCode + if value is not None: +- value = interpreter.evaluate(string.strip(value), locals) ++ value = interpreter.evaluate(value.strip(), locals) + interpreter.significate(self.key, value) + + def string(self): +@@ -1440,7 +1433,7 @@ + scanner.acquire() + i = scanner.complex('[', ']', 0) + self.contents = scanner.chop(i, 1) +- fields = string.split(string.strip(self.contents), ' ', 1) ++ fields = self.contents.strip().split(' ', 1) + if len(fields) > 1: + self.type, self.rest = fields + else: +@@ -1448,7 +1441,7 @@ + self.rest = None + self.subtokens = [] + if self.type in self.GREEDY_TYPES and self.rest is None: +- raise ParseError, "control '%s' needs arguments" % self.type ++ raise ParseError("control '%s' needs arguments" % self.type) + if self.type in self.PRIMARY_TYPES: + self.subscan(scanner, self.type) + self.kind = 'primary' +@@ -1459,7 +1452,7 @@ + elif self.type in self.END_TYPES: + self.kind = 'end' + else: +- raise ParseError, "unknown control markup: '%s'" % self.type ++ raise ParseError("unknown control markup: '%s'" % self.type) + scanner.release() + + def subscan(self, scanner, primary): +@@ -1467,13 +1460,11 @@ + while True: + token = scanner.one() + if token is None: +- raise TransientParseError, \ +- "control '%s' needs more tokens" % primary ++ raise TransientParseError("control '%s' needs more tokens" % primary) + if isinstance(token, ControlToken) and \ + token.type in self.END_TYPES: + if token.rest != primary: +- raise ParseError, \ +- "control must end with 'end %s'" % primary ++ raise ParseError("control must end with 'end %s'" % primary) + break + self.subtokens.append(token) + +@@ -1492,8 +1483,7 @@ + if isinstance(subtoken, ControlToken) and \ + subtoken.kind == 'secondary': + if subtoken.type not in allowed: +- raise ParseError, \ +- "control unexpected secondary: '%s'" % subtoken.type ++ raise ParseError("control unexpected secondary: '%s'" % subtoken.type) + latest = [] + result.append((subtoken, latest)) + else: +@@ -1510,8 +1500,7 @@ + elseTokens = info.pop()[1] + for secondary, subtokens in info: + if secondary.type not in ('if', 'elif'): +- raise ParseError, \ +- "control 'if' unexpected secondary: '%s'" % secondary.type ++ raise ParseError("control 'if' unexpected secondary: '%s'" % secondary.type) + if interpreter.evaluate(secondary.rest, locals): + self.subrun(subtokens, interpreter, locals) + break +@@ -1521,14 +1510,14 @@ + elif self.type == 'for': + sides = self.IN_RE.split(self.rest, 1) + if len(sides) != 2: +- raise ParseError, "control expected 'for x in seq'" ++ raise ParseError("control expected 'for x in seq'") + iterator, sequenceCode = sides + info = self.build(['else']) + elseTokens = None + if info[-1][0].type == 'else': + elseTokens = info.pop()[1] + if len(info) != 1: +- raise ParseError, "control 'for' expects at most one 'else'" ++ raise ParseError("control 'for' expects at most one 'else'") + sequence = interpreter.evaluate(sequenceCode, locals) + for element in sequence: + try: +@@ -1548,7 +1537,7 @@ + if info[-1][0].type == 'else': + elseTokens = info.pop()[1] + if len(info) != 1: +- raise ParseError, "control 'while' expects at most one 'else'" ++ raise ParseError("control 'while' expects at most one 'else'") + atLeastOnce = False + while True: + try: +@@ -1565,24 +1554,22 @@ + elif self.type == 'try': + info = self.build(['except', 'finally']) + if len(info) == 1: +- raise ParseError, "control 'try' needs 'except' or 'finally'" ++ raise ParseError("control 'try' needs 'except' or 'finally'") + type = info[-1][0].type + if type == 'except': + for secondary, _tokens in info[1:]: + if secondary.type != 'except': +- raise ParseError, \ +- "control 'try' cannot have 'except' and 'finally'" ++ raise ParseError("control 'try' cannot have 'except' and 'finally'") + else: + assert type == 'finally' + if len(info) != 2: +- raise ParseError, \ +- "control 'try' can only have one 'finally'" ++ raise ParseError("control 'try' can only have one 'finally'") + if type == 'except': + try: + self.subrun(info[0][1], interpreter, locals) + except FlowError: + raise +- except Exception, e: ++ except Exception as e: + for secondary, tokens in info[1:]: + exception, variable = interpreter.clause(secondary.rest) + if variable is not None: +@@ -1598,9 +1585,9 @@ + finally: + self.subrun(info[1][1], interpreter, locals) + elif self.type == 'continue': +- raise ContinueFlow, "control 'continue' without 'for', 'while'" ++ raise ContinueFlow("control 'continue' without 'for', 'while'") + elif self.type == 'break': +- raise BreakFlow, "control 'break' without 'for', 'while'" ++ raise BreakFlow("control 'break' without 'for', 'while'") + elif self.type == 'def': + signature = self.rest + definition = self.substring() +@@ -1610,10 +1597,9 @@ + (signature, definition, interpreter.pseudo, definition) + interpreter.execute(code, locals) + elif self.type == 'end': +- raise ParseError, "control 'end' requires primary markup" ++ raise ParseError("control 'end' requires primary markup") + else: +- raise ParseError, \ +- "control '%s' cannot be at this level" % self.type ++ raise ParseError("control '%s' cannot be at this level" % self.type) + interpreter.invoke('afterControl') + + def subrun(self, tokens, interpreter, locals): +@@ -1622,7 +1608,7 @@ + token.run(interpreter, locals) + + def substring(self): +- return string.join(map(str, self.subtokens), '') ++ return ''.join(list(map(str, self.subtokens))) + + def string(self): + if self.kind == 'primary': +@@ -1666,9 +1652,12 @@ + self.buffer = data + self.lock = 0 + +- def __nonzero__(self): return self.pointer < len(self.buffer) ++ def __bool__(self): return self.pointer < len(self.buffer) + def __len__(self): return len(self.buffer) - self.pointer +- def __getitem__(self, index): return self.buffer[self.pointer + index] ++ def __getitem__(self, index): ++ if isinstance(index, slice): ++ return ''.join([self.buffer[x] for x in range(self.pointer + (index.start if index.start else 0), (self.pointer + index.stop) if index.stop is not None else len(self.buffer), index.step if index.step else 1)]) ++ return self.buffer[self.pointer + index] + + def __getslice__(self, start, stop): + if stop > len(self): +@@ -1682,7 +1671,7 @@ + def retreat(self, count=1): + self.pointer = self.pointer - count + if self.pointer < 0: +- raise ParseError, "can't retreat back over synced out chars" ++ raise ParseError("can't retreat back over synced out chars") + + def set(self, data): + """Start the scanner digesting a new batch of data; start the pointer +@@ -1702,7 +1691,7 @@ + assert slop == 0 + count = len(self) + if count > len(self): +- raise TransientParseError, "not enough data to read" ++ raise TransientParseError("not enough data to read") + result = self[:count] + self.advance(count + slop) + return result +@@ -1735,7 +1724,7 @@ + """Read count chars starting from i; raise a transient error if + there aren't enough characters remaining.""" + if len(self) < i + count: +- raise TransientParseError, "need more data to read" ++ raise TransientParseError("need more data to read") + else: + return self[i:i + count] + +@@ -1750,7 +1739,7 @@ + if self[i] == quote: + return quote + else: +- raise TransientParseError, "need to scan for rest of quote" ++ raise TransientParseError("need to scan for rest of quote") + if self[i + 1] == self[i + 2] == quote: + quote = quote * 3 + if quote is not None: +@@ -1769,9 +1758,9 @@ + def find(self, sub, start=0, end=None): + """Find the next occurrence of the character, or return -1.""" + if end is not None: +- return string.find(self.rest(), sub, start, end) ++ return self.rest().find(sub, start, end) + else: +- return string.find(self.rest(), sub, start) ++ return self.rest().find(sub, start) + + def last(self, char, start=0, end=None): + """Find the first character that is _not_ the specified character.""" +@@ -1783,7 +1772,7 @@ + return i + i = i + 1 + else: +- raise TransientParseError, "expecting other than %s" % char ++ raise TransientParseError("expecting other than %s" % char) + + def next(self, target, start=0, end=None, mandatory=False): + """Scan for the next occurrence of one of the characters in +@@ -1813,9 +1802,9 @@ + i = i + 1 + else: + if mandatory: +- raise ParseError, "expecting %s, not found" % target ++ raise ParseError("expecting %s, not found" % target) + else: +- raise TransientParseError, "expecting ending character" ++ raise TransientParseError("expecting ending character") + + def quote(self, start=0, end=None, mandatory=False): + """Scan for the end of the next quote.""" +@@ -1837,9 +1826,9 @@ + i = i + 1 + else: + if mandatory: +- raise ParseError, "expecting end of string literal" ++ raise ParseError("expecting end of string literal") + else: +- raise TransientParseError, "expecting end of string literal" ++ raise TransientParseError("expecting end of string literal") + + def nested(self, enter, exit, start=0, end=None): + """Scan from i for an ending sequence, respecting entries and exits +@@ -1858,7 +1847,7 @@ + return i + i = i + 1 + else: +- raise TransientParseError, "expecting end of complex expression" ++ raise TransientParseError("expecting end of complex expression") + + def complex(self, enter, exit, start=0, end=None, skip=None): + """Scan from i for an ending sequence, respecting quotes, +@@ -1893,7 +1882,7 @@ + last = c + i = i + 1 + else: +- raise TransientParseError, "expecting end of complex expression" ++ raise TransientParseError("expecting end of complex expression") + + def word(self, start=0): + """Scan from i for a simple word.""" +@@ -1904,7 +1893,7 @@ + return i + i = i + 1 + else: +- raise TransientParseError, "expecting end of word" ++ raise TransientParseError("expecting end of word") + + def phrase(self, start=0): + """Scan from i for a phrase (e.g., 'word', 'f(a, b, c)', 'a[i]', or +@@ -1914,7 +1903,7 @@ + while i < len(self) and self[i] in '([{': + enter = self[i] + if enter == '{': +- raise ParseError, "curly braces can't open simple expressions" ++ raise ParseError("curly braces can't open simple expressions") + exit = ENDING_CHARS[enter] + i = self.complex(enter, exit, i + 1) + 1 + return i +@@ -1958,7 +1947,7 @@ + elif first in firsts: + break + else: +- raise ParseError, "unknown markup: %s%s" % (self.prefix, first) ++ raise ParseError("unknown markup: %s%s" % (self.prefix, first)) + token = factory(self.prefix, first) + try: + token.scan(self) +@@ -2087,16 +2076,16 @@ + self.globals = {} + # Make sure that there is no collision between two interpreters' + # globals. +- if self.globals.has_key(self.pseudo): ++ if self.pseudo in self.globals: + if self.globals[self.pseudo] is not self: +- raise Error, "interpreter globals collision" ++ raise Error("interpreter globals collision") + self.globals[self.pseudo] = self + + def unfix(self): + """Remove the pseudomodule (if present) from the globals.""" + UNWANTED_KEYS = [self.pseudo, '__builtins__'] + for unwantedKey in UNWANTED_KEYS: +- if self.globals.has_key(unwantedKey): ++ if unwantedKey in self.globals: + del self.globals[unwantedKey] + + def update(self, other): +@@ -2187,7 +2176,7 @@ + + def include(self, fileOrFilename, locals=None): + """Do an include pass on a file or filename.""" +- if type(fileOrFilename) is types.StringType: ++ if isinstance(fileOrFilename, bytes): + # Either it's a string representing a filename ... + filename = fileOrFilename + name = filename +@@ -2202,7 +2191,7 @@ + + def expand(self, data, locals=None): + """Do an explicit expansion on a subordinate stream.""" +- outFile = StringIO.StringIO() ++ outFile = StringIO() + stream = Stream(outFile) + self.invoke('beforeExpand', string=data, locals=locals) + self.streams.push(stream) +@@ -2230,7 +2219,7 @@ + except TransientParseError: + pass + result.append(data[i:]) +- result = string.join(result, '') ++ result = ''.join(result) + self.invoke('afterQuote', result=result) + return result + +@@ -2242,7 +2231,7 @@ + for char in data: + if char < ' ' or char > '~': + charOrd = ord(char) +- if Interpreter.ESCAPE_CODES.has_key(charOrd): ++ if charOrd in Interpreter.ESCAPE_CODES: + result.append(self.prefix + '\\' + \ + Interpreter.ESCAPE_CODES[charOrd]) + else: +@@ -2251,7 +2240,7 @@ + result.append(self.prefix + '\\' + char) + else: + result.append(char) +- result = string.join(result, '') ++ result = ''.join(result) + self.invoke('afterEscape', result=result) + return result + +@@ -2261,21 +2250,21 @@ + """Wrap around an application of a callable and handle errors. + Return whether no error occurred.""" + try: +- apply(callable, args) ++ callable(*args) + self.reset() + return True +- except KeyboardInterrupt, e: ++ except KeyboardInterrupt as e: + # Handle keyboard interrupts specially: we should always exit + # from these. + self.fail(e, True) +- except Exception, e: ++ except Exception as e: + # A standard exception (other than a keyboard interrupt). + self.fail(e) + except: + # If we get here, then either it's an exception not derived from + # Exception or it's a string exception, so get the error type + # from the sys module. +- e = sys.exc_type ++ e = sys.exc_info()[0] + self.fail(e) + # An error occurred if we leak through to here, so do cleanup. + self.reset() +@@ -2327,7 +2316,7 @@ + if self.options.get(BANGPATH_OPT, True) and self.prefix: + # Replace a bangpath at the beginning of the first line + # with an EmPy comment. +- if string.find(line, BANGPATH) == 0: ++ if line.startswith(BANGPATH): + line = self.prefix + '#' + line[2:] + first = False + if line: +@@ -2406,9 +2395,9 @@ + result = [] + stack = [result] + for garbage in self.ASSIGN_TOKEN_RE.split(name): +- garbage = string.strip(garbage) ++ garbage = garbage.strip() + if garbage: +- raise ParseError, "unexpected assignment token: '%s'" % garbage ++ raise ParseError("unexpected assignment token: '%s'" % garbage) + tokens = self.ASSIGN_TOKEN_RE.findall(name) + # While processing, put a None token at the start of any list in which + # commas actually appear. +@@ -2459,12 +2448,12 @@ + try: + values = tuple(values) + except TypeError: +- raise TypeError, "unpack non-sequence" ++ raise TypeError("unpack non-sequence") + if len(names) != len(values): +- raise ValueError, "unpack tuple of wrong size" ++ raise ValueError("unpack tuple of wrong size") + for i in range(len(names)): + name = names[i] +- if type(name) is types.StringType: ++ if isinstance(name, bytes) or isinstance(name, str): + self.atomic(name, values[i], locals) + else: + self.multi(name, values[i], locals) +@@ -2475,7 +2464,7 @@ + left = self.tokenize(name) + # The return value of tokenize can either be a string or a list of + # (lists of) strings. +- if type(left) is types.StringType: ++ if isinstance(left, bytes) or isinstance(left, str): + self.atomic(left, value, locals) + else: + self.multi(left, value, locals) +@@ -2493,11 +2482,11 @@ + self.invoke('beforeClause', catch=catch, locals=locals) + if catch is None: + exceptionCode, variable = None, None +- elif string.find(catch, ',') >= 0: +- exceptionCode, variable = string.split(string.strip(catch), ',', 1) +- variable = string.strip(variable) ++ elif catch.find(',') >= 0: ++ exceptionCode, variable = catch.strip().split(',', 1) ++ variable = variable.strip() + else: +- exceptionCode, variable = string.strip(catch), None ++ exceptionCode, variable = catch.strip(), None + if not exceptionCode: + exception = Exception + else: +@@ -2520,11 +2509,11 @@ + defined either in the locals or the globals.""" + self.invoke('beforeDefined', name=name, local=local) + if locals is not None: +- if locals.has_key(name): ++ if name in locals: + result = True + else: + result = False +- elif self.globals.has_key(name): ++ elif name in self.globals: + result = True + else: + result = False +@@ -2560,20 +2549,20 @@ + # If there are any carriage returns (as opposed to linefeeds/newlines) + # in the statements code, then remove them. Even on DOS/Windows + # platforms, +- if string.find(statements, '\r') >= 0: +- statements = string.replace(statements, '\r', '') ++ if statements.find('\r') >= 0: ++ statements = statements.replace('\r', '') + # If there are no newlines in the statements code, then strip any + # leading or trailing whitespace. +- if string.find(statements, '\n') < 0: +- statements = string.strip(statements) ++ if statements.find('\n') < 0: ++ statements = statements.strip() + self.push() + try: + self.invoke('beforeExecute', \ + statements=statements, locals=locals) + if locals is not None: +- exec statements in self.globals, locals ++ exec(statements, self.globals, locals) + else: +- exec statements in self.globals ++ exec(statements, self.globals) + self.invoke('afterExecute') + finally: + self.pop() +@@ -2587,9 +2576,9 @@ + source=source, locals=locals) + code = compile(source, '<single>', 'single') + if locals is not None: +- exec code in self.globals, locals ++ exec(code, self.globals, locals) + else: +- exec code in self.globals ++ exec(code, self.globals) + self.invoke('afterSingle') + finally: + self.pop() +@@ -2621,7 +2610,7 @@ + hook.push() + try: + method = getattr(hook, _name) +- apply(method, (), keywords) ++ method(*(), **keywords) + finally: + hook.pop() + +@@ -2674,7 +2663,7 @@ + # installed it before ... + if Interpreter._wasProxyInstalled: + # ... and if so, we have a proxy problem. +- raise Error, "interpreter stdout proxy lost" ++ raise Error("interpreter stdout proxy lost") + else: + # Otherwise, install the proxy and set the flag. + sys.stdout = ProxyFile(sys.stdout) +@@ -2780,7 +2769,7 @@ + + def invokeHook(self, _name, **keywords): + """Manually invoke a hook.""" +- apply(self.invoke, (_name,), keywords) ++ self.invoke(*(_name,), **keywords) + + # Callbacks. + +@@ -2800,7 +2789,7 @@ + """Invoke the callback.""" + if self.callback is None: + if self.options.get(CALLBACK_OPT, False): +- raise Error, "custom markup invoked with no defined callback" ++ raise Error("custom markup invoked with no defined callback") + else: + self.callback(contents) + +@@ -2810,7 +2799,7 @@ + """Flatten the contents of the pseudo-module into the globals + namespace.""" + if keys is None: +- keys = self.__dict__.keys() + self.__class__.__dict__.keys() ++ keys = list(self.__dict__.keys()) + list(self.__class__.__dict__.keys()) + dict = {} + for key in keys: + # The pseudomodule is really a class instance, so we need to +@@ -2879,8 +2868,7 @@ + + def getAllDiversions(self): + """Get the names of all existing diversions.""" +- names = self.stream().diversions.keys() +- names.sort() ++ names = sorted(list(self.stream().diversions.keys())) + return names + + # Filter. +@@ -2940,7 +2928,7 @@ + self.documents = {} + + def scan(self, basename, extensions=DEFAULT_EMPY_EXTENSIONS): +- if type(extensions) is types.StringType: ++ if isinstance(extensions, bytes): + extensions = (extensions,) + def _noCriteria(x): + return True +@@ -2988,7 +2976,7 @@ + match = self.SIGNIFICATOR_RE.search(line) + if match: + key, valueS = match.groups() +- valueS = string.strip(valueS) ++ valueS = valueS.strip() + if valueS: + value = eval(valueS) + else: +@@ -3027,7 +3015,7 @@ + """Get data from the current environment. If the default is True + or False, then presume that we're only interested in the existence + or non-existence of the environment variable.""" +- if os.environ.has_key(name): ++ if name in os.environ: + # Do the True/False test by value for future compatibility. + if default == False or default == True: + return True +@@ -3110,7 +3098,7 @@ + _pauseAtEnd = False + _relativePath = False + if _extraArguments is not None: +- _extraArguments = string.split(_extraArguments) ++ _extraArguments = _extraArguments.split() + args = _extraArguments + args + # Parse the arguments. + pairs, remainder = getopt.getopt(args, 'VhHvkp:m:frino:a:buBP:I:D:E:F:', ['version', 'help', 'extended-help', 'verbose', 'null-hook', 'suppress-errors', 'prefix=', 'no-prefix', 'module=', 'flatten', 'raw-errors', 'interactive', 'no-override-stdout', 'binary', 'chunk-size=', 'output=' 'append=', 'preprocess=', 'import=', 'define=', 'execute=', 'execute-file=', 'buffered-output', 'pause-at-end', 'relative-path', 'no-callback-error', 'no-bangpath-processing', 'unicode', 'unicode-encoding=', 'unicode-input-encoding=', 'unicode-output-encoding=', 'unicode-errors=', 'unicode-input-errors=', 'unicode-output-errors=']) +@@ -3160,8 +3148,8 @@ + elif option in ('-P', '--preprocess'): + _preprocessing.append(('pre', argument)) + elif option in ('-I', '--import'): +- for module in string.split(argument, ','): +- module = string.strip(module) ++ for module in argument.split(','): ++ module = module.strip() + _preprocessing.append(('import', module)) + elif option in ('-D', '--define'): + _preprocessing.append(('define', argument)) +@@ -3200,18 +3188,18 @@ + _unicodeInputErrors, _unicodeOutputErrors) + # Now initialize the output file if something has already been selected. + if _output is not None: +- _output = apply(AbstractFile, _output) ++ _output = AbstractFile(*_output) + # Set up the main filename and the argument. + if not remainder: + remainder.append('-') + filename, arguments = remainder[0], remainder[1:] + # Set up the interpreter. + if _options[BUFFERED_OPT] and _output is None: +- raise ValueError, "-b only makes sense with -o or -a arguments" ++ raise ValueError("-b only makes sense with -o or -a arguments") + if _prefix == 'None': + _prefix = None +- if _prefix and type(_prefix) is types.StringType and len(_prefix) != 1: +- raise Error, "prefix must be single-character string" ++ if _prefix and isinstance(_prefix, bytes) and len(_prefix) != 1: ++ raise Error("prefix must be single-character string") + interpreter = Interpreter(output=_output, \ + argv=remainder, \ + prefix=_prefix, \ +@@ -3228,7 +3216,7 @@ + name = thing + elif which == 'define': + command = interpreter.string +- if string.find(thing, '=') >= 0: ++ if thing.find('=') >= 0: + target = '%s{%s}' % (_prefix, thing) + else: + target = '%s{%s = None}' % (_prefix, thing) +@@ -3240,7 +3228,7 @@ + elif which == 'file': + command = interpreter.string + name = '<file:%d (%s)>' % (i, thing) +- target = '%s{execfile("""%s""")}' % (_prefix, thing) ++ target = '%s{exec(open("""%s""").read())}' % (_prefix, thing) + elif which == 'import': + command = interpreter.string + name = '<import:%d>' % i +@@ -3278,7 +3266,7 @@ + # Finally, if we should pause at the end, do it. + if _pauseAtEnd: + try: +- raw_input() ++ input() + except EOFError: + pass + +--- a/sample.em ++++ b/sample.em +@@ -19,7 +19,7 @@ + @{ + import sys + # This is just a normal Python comment. +-print "This is more text." ++print("This is more text.") + }@ + @# Note the @{ ... }@ convention to suppress the newline following the }. + @# Also note that comments are completely tossed: This is not expanded: @(x). +@@ -40,11 +40,11 @@ + Statements: @{sys.stdout.write("%d**2 = %d" % (x, square(x)))}. + Whitespace too: @{ sys.stdout.write("%d**2 = %d (still)" % (x, square(x))) }. + @{ +-print "But only on single-line statement expansions." ++print("But only on single-line statement expansions.") + if 1: +- print "Internal whitespace on multi-line statements is significant." ++ print("Internal whitespace on multi-line statements is significant.") + for i in range(2): +- print "Normal Python indentation rules must be followed here." ++ print("Normal Python indentation rules must be followed here.") + }@ + Simple expressions: x is @x, l is @l, s is "@s," and @x squared is @square(x). + Literals too: x is @x, but would be written @@x. +@@ -58,7 +58,7 @@ + Same with functions: @square(x) is @square( x ). + The same applies to the other forms. + Involved: The legal digits are @string.digits. +-More involved: The names of my friends are @string.join(friends, ', '). ++More involved: The names of my friends are @(', '.join(friends)). + Following expressions: Pluralize "@word" as "@(word)s," or maybe "@word@ s." + By default str is used (@s), but you can use repr if you want (@`s`). + Conditional expressions: @(x ? "x is true" ! "x is false"). +@@ -213,9 +213,9 @@ + @# Filters. + @{import string}@ + This line should be in mixed case. +-@empy.setFilter(string.lower)@ ++@empy.setFilter(str.lower)@ + This line should be all lowercase. +-@empy.setFilter(string.upper)@ ++@empy.setFilter(str.upper)@ + This line should be all uppercase (how gauche). + @empy.setFilter([em.LineBufferedFilter(), lambda x: '[%s]\n' % x[:-1]])@ + This line should be bracketed. +@@ -226,7 +226,7 @@ + This line should not appear at all! + @empy.resetFilter()@ + This line should be back to mixed case. +-@empy.attachFilter(string.upper)@ ++@empy.attachFilter(str.upper)@ + @empy.attachFilter(em.LineBufferedFilter())@ + @empy.attachFilter(lambda x: '[%s]\n' % x[:-1])@ + This line should be all uppercase with brackets. +@@ -235,10 +235,10 @@ + + @# Contexts, metaoperations. + @{ +-import StringIO +-def context(): +- return "%s:%d" % empy.identify() +-stringFile = StringIO.StringIO("2 + 2 = @(2 + 2) [@context()].\n") ++from __future__ import unicode_literals ++from io import StringIO ++def context(): return "%s:%d" % empy.identify() ++stringFile = StringIO("2 + 2 = @(2 + 2) [@context()].\n") + }@ + The new context is @context(). + File inclusion [@context()]: @empy.include(stringFile)@ +--- a/test.sh ++++ b/test.sh +@@ -13,7 +13,7 @@ + SAMPLE=sample.em + BENCH=sample.bench + +-if $PYTHON -c 'import sys; print sys.version' > /dev/null ++if $PYTHON -c 'import sys; print(sys.version)' > /dev/null + then + : + else diff --git a/debian/python3-empy.dirs b/debian/python3-empy.dirs new file mode 100644 index 0000000..c703cf8 --- /dev/null +++ b/debian/python3-empy.dirs @@ -0,0 +1 @@ +usr/bin/ diff --git a/debian/python3-empy.manpages b/debian/python3-empy.manpages new file mode 100644 index 0000000..542e2bf --- /dev/null +++ b/debian/python3-empy.manpages @@ -0,0 +1 @@ +debian/empy.1 -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org