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

Reply via email to