r47243 - Merge forward
hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Thu, 14 Apr 2016 20:22:24 -0600 (MDT)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: hawkowl
Date: Thu Apr 14 20:22:18 2016
New Revision: 47243
Added:
branches/moar-windows-8025-7/twisted/topfiles/8025.misc
Modified:
branches/moar-windows-8025-7/.gitignore
branches/moar-windows-8025-7/twisted/internet/_dumbwin32proc.py
branches/moar-windows-8025-7/twisted/internet/_pollingfile.py
branches/moar-windows-8025-7/twisted/internet/_win32stdio.py
branches/moar-windows-8025-7/twisted/internet/test/_win32ifaces.py
branches/moar-windows-8025-7/twisted/internet/test/process_cli.py
branches/moar-windows-8025-7/twisted/internet/test/test_tcp.py
branches/moar-windows-8025-7/twisted/internet/test/test_win32events.py
branches/moar-windows-8025-7/twisted/internet/win32eventreactor.py
branches/moar-windows-8025-7/twisted/logger/test/test_stdlib.py
branches/moar-windows-8025-7/twisted/python/dist3.py
branches/moar-windows-8025-7/twisted/python/filepath.py
branches/moar-windows-8025-7/twisted/python/lockfile.py
branches/moar-windows-8025-7/twisted/python/log.py
branches/moar-windows-8025-7/twisted/python/test/test_deprecate.py
branches/moar-windows-8025-7/twisted/python/zippath.py
branches/moar-windows-8025-7/twisted/scripts/_twistw.py
branches/moar-windows-8025-7/twisted/scripts/trial.py
branches/moar-windows-8025-7/twisted/test/process_stdinreader.py
branches/moar-windows-8025-7/twisted/test/test_compat.py
branches/moar-windows-8025-7/twisted/test/test_internet.py
branches/moar-windows-8025-7/twisted/test/test_lockfile.py
branches/moar-windows-8025-7/twisted/test/test_paths.py
branches/moar-windows-8025-7/twisted/test/test_process.py
branches/moar-windows-8025-7/twisted/test/test_tcp.py
branches/moar-windows-8025-7/twisted/trial/test/test_runner.py
Log:
Merge forward
Modified: branches/moar-windows-8025-7/.gitignore
==============================================================================
--- branches/moar-windows-8025-7/.gitignore (original)
+++ branches/moar-windows-8025-7/.gitignore Thu Apr 14 20:22:18 2016
@@ -14,3 +14,5 @@
*~
*.lock
apidocs/
+.vs/
+*.pyproj
\ No newline at end of file
Modified: branches/moar-windows-8025-7/twisted/internet/_dumbwin32proc.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/_dumbwin32proc.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/_dumbwin32proc.py Thu Apr 14 20:22:18 2016
@@ -6,6 +6,8 @@
http://isometri.cc/strips/gates_in_the_head
"""
+from __future__ import absolute_import, division, print_function
+
import os
# Win32 imports
@@ -26,6 +28,7 @@
from zope.interface import implementer
from twisted.internet.interfaces import IProcessTransport, IConsumer, IProducer
+from twisted.python.compat import items, _PY3, unicode
from twisted.python.win32 import quoteArguments
from twisted.internet import error
@@ -35,7 +38,7 @@
def debug(msg):
import sys
- print msg
+ print(msg)
sys.stdout.flush()
class _Reaper(_pollingfile._PollableResource):
@@ -52,6 +55,7 @@
return 0
+
def _findShebang(filename):
"""
Look for a #! line, and return the value following the #! if one exists, or
@@ -73,10 +77,12 @@
@return: a str representing another filename.
"""
- f = file(filename, 'rU')
- if f.read(2) == '#!':
- exe = f.readline(1024).strip('\n')
- return exe
+ with open(filename, 'rU') as f:
+ if f.read(2) == '#!':
+ exe = f.readline(1024).strip('\n')
+ return exe
+
+
def _invalidWin32App(pywinerr):
"""
@@ -97,7 +103,8 @@
@implementer(IProcessTransport, IConsumer, IProducer)
class Process(_pollingfile._PollingTimer, BaseProcess):
- """A process that integrates with the Twisted event loop.
+ """
+ A process that integrates with the Twisted event loop.
If your subprocess is a python program, you need to:
@@ -169,7 +176,16 @@
env = os.environ.copy()
env.update(environment or {})
+ if _PY3:
+ # Make sure all the arguments are str
+ args = [x.decode('mbcs') if isinstance(x, bytes) else x
+ for x in args]
+
cmdline = quoteArguments(args)
+
+ if _PY3 and isinstance(command, bytes):
+ command = command.decode('mbcs')
+
# TODO: error detection here. See #2787 and #4184.
def doCreate():
self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
@@ -177,18 +193,26 @@
try:
try:
doCreate()
- except TypeError, e:
+ except TypeError as e:
# win32process.CreateProcess cannot deal with mixed
# str/unicode environment, so we make it all Unicode
if e.args != ('All dictionary items must be strings, or '
'all must be unicode',):
raise
newenv = {}
- for key, value in env.items():
- newenv[unicode(key)] = unicode(value)
+ for key, value in items(env):
+
+ if not isinstance(value, unicode):
+ value = value.decode('mbcs')
+
+ if not isinstance(key, unicode):
+ key = key.decode('mbcs')
+
+ newenv[key] = value
+
env = newenv
doCreate()
- except pywintypes.error, pwte:
+ except pywintypes.error as pwte:
if not _invalidWin32App(pwte):
# This behavior isn't _really_ documented, but let's make it
# consistent with the behavior that is documented.
@@ -210,7 +234,7 @@
try:
# Let's try again.
doCreate()
- except pywintypes.error, pwte2:
+ except pywintypes.error as pwte2:
# d'oh, failed again!
if _invalidWin32App(pwte2):
raise OSError(
@@ -265,7 +289,7 @@
"""
Write data to the process' stdin.
- @type data: C{str}
+ @type data: C{bytes}
"""
self.stdin.write(data)
@@ -274,7 +298,7 @@
"""
Write data to the process' stdin.
- @type data: C{list} of C{str}
+ @type data: C{list} of C{bytes}
"""
self.stdin.writeSequence(seq)
@@ -291,7 +315,7 @@
@type fd: C{int}
@param data: The bytes to write.
- @type data: C{str}
+ @type data: C{bytes}
@return: C{None}
Modified: branches/moar-windows-8025-7/twisted/internet/_pollingfile.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/_pollingfile.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/_pollingfile.py Thu Apr 14 20:22:18 2016
@@ -7,8 +7,11 @@
select() - this is pretty much only useful on Windows.
"""
+from __future__ import absolute_import, division
from zope.interface import implementer
+
+from twisted.python.compat import unicode
from twisted.internet.interfaces import IConsumer, IPushProducer
@@ -128,7 +131,7 @@
finished = 1
break
- dataBuf = ''.join(fullDataRead)
+ dataBuf = b''.join(fullDataRead)
if dataBuf:
self.receivedCallback(dataBuf)
if finished:
@@ -272,7 +275,7 @@
self.writeConnectionLost()
return 0
try:
- win32file.WriteFile(self.writePipe, '', None)
+ win32file.WriteFile(self.writePipe, b'', None)
except pywintypes.error:
self.writeConnectionLost()
return numBytesWritten
Modified: branches/moar-windows-8025-7/twisted/internet/_win32stdio.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/_win32stdio.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/_win32stdio.py Thu Apr 14 20:22:18 2016
@@ -4,13 +4,16 @@
Windows-specific implementation of the L{twisted.internet.stdio} interface.
"""
+from __future__ import absolute_import, division
+
import win32api
-import os, msvcrt
+import os
+import msvcrt
from zope.interface import implementer
-from twisted.internet.interfaces import IHalfCloseableProtocol, ITransport, IAddress
-from twisted.internet.interfaces import IConsumer, IPushProducer
+from twisted.internet.interfaces import IHalfCloseableProtocol, ITransport
+from twisted.internet.interfaces import IConsumer, IPushProducer, IAddress
from twisted.internet import _pollingfile, main
from twisted.python.failure import Failure
@@ -83,7 +86,7 @@
self.stdout.write(data)
def writeSequence(self, seq):
- self.stdout.write(''.join(seq))
+ self.stdout.write(b''.join(seq))
def loseConnection(self):
self.disconnecting = True
@@ -118,4 +121,3 @@
def resumeProducing(self):
self.stdin.resumeProducing()
-
Modified: branches/moar-windows-8025-7/twisted/internet/test/_win32ifaces.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/test/_win32ifaces.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/test/_win32ifaces.py Thu Apr 14 20:22:18 2016
@@ -5,6 +5,10 @@
Windows implementation of local network interface enumeration.
"""
+from __future__ import absolute_import, division
+
+from twisted.python.compat import nativeString
+
from socket import socket, AF_INET6, SOCK_STREAM
from ctypes import (
WinDLL, byref, create_string_buffer, c_int, c_void_p,
@@ -115,5 +119,5 @@
byref(retBytes))
if ret:
raise RuntimeError("WSAAddressToString failure")
- retList.append(string_at(addressStringBuf))
+ retList.append(nativeString(string_at(addressStringBuf)))
return [addr for addr in retList if '%' in addr]
Modified: branches/moar-windows-8025-7/twisted/internet/test/process_cli.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/test/process_cli.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/test/process_cli.py Thu Apr 14 20:22:18 2016
@@ -1,4 +1,8 @@
-import sys, os
+from __future__ import absolute_import, division
+
+import sys
+import os
+
try:
# On Windows, stdout is not opened in binary mode by default,
# so newline characters are munged on writing, interfering with
@@ -16,8 +20,8 @@
if sys.version_info < (3, 0):
stdout = sys.stdout
else:
- res = res.encode("utf8", "surrogateescape")
stdout = sys.stdout.buffer
+ res = res.encode(sys.getfilesystemencoding(), "surrogateescape")
stdout.write(res)
stdout.flush()
Modified: branches/moar-windows-8025-7/twisted/internet/test/test_tcp.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/test/test_tcp.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/test/test_tcp.py Thu Apr 14 20:22:18 2016
@@ -1102,8 +1102,7 @@
try:
connect(client, (port.getHost().host, port.getHost().port))
except socket.error as e:
- errnum, message = e.args
- self.assertIn(errnum, (errno.EINPROGRESS, errno.EWOULDBLOCK))
+ self.assertIn(e.errno, (errno.EINPROGRESS, errno.EWOULDBLOCK))
self.runReactor(reactor)
@@ -1185,8 +1184,7 @@
try:
connect(client, (port.getHost().host, port.getHost().port))
except socket.error as e:
- errnum, message = e.args
- self.assertIn(errnum, (errno.EINPROGRESS, errno.EWOULDBLOCK))
+ self.assertIn(e.errno, (errno.EINPROGRESS, errno.EWOULDBLOCK))
self.runReactor(reactor)
return factory.address
Modified: branches/moar-windows-8025-7/twisted/internet/test/test_win32events.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/test/test_win32events.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/test/test_win32events.py Thu Apr 14 20:22:18 2016
@@ -5,7 +5,10 @@
Tests for implementations of L{IReactorWin32Events}.
"""
-from thread import get_ident
+try:
+ from thread import get_ident
+except ImportError:
+ from threading import get_ident
try:
import win32event
Modified: branches/moar-windows-8025-7/twisted/internet/win32eventreactor.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/internet/win32eventreactor.py (original)
+++ branches/moar-windows-8025-7/twisted/internet/win32eventreactor.py Thu Apr 14 20:22:18 2016
@@ -1,11 +1,11 @@
+# -*- test-case-name: twisted.internet.test.test_win32events -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
-
"""
A win32event based implementation of the Twisted main loop.
-This requires pywin32 (formerly win32all) or ActivePython to be installed.
+This requires pywin32 or ActivePython to be installed.
To install the event loop (and you should do this before any connections,
listeners or connectors are added)::
@@ -17,36 +17,15 @@
1. WaitForMultipleObjects and thus the event loop can only handle 64 objects.
2. Process running has some problems (see L{Process} docstring).
-
-TODO:
- 1. Event loop handling of writes is *very* problematic (this is causing failed tests).
- Switch to doing it the correct way, whatever that means (see below).
- 2. Replace icky socket loopback waker with event based waker (use dummyEvent object)
- 3. Switch everyone to using Free Software so we don't have to deal with proprietary APIs.
-
-
-ALTERNATIVE SOLUTIONS:
- - IIRC, sockets can only be registered once. So we switch to a structure
- like the poll() reactor, thus allowing us to deal with write events in
- a decent fashion. This should allow us to pass tests, but we're still
- limited to 64 events.
-
-Or:
-
- - Instead of doing a reactor, we make this an addon to the select reactor.
- The WFMO event loop runs in a separate thread. This means no need to maintain
- separate code for networking, 64 event limit doesn't apply to sockets,
- we can run processes and other win32 stuff in default event loop. The
- only problem is that we're stuck with the icky socket based waker.
- Another benefit is that this could be extended to support >64 events
- in a simpler manner than the previous solution.
-
-The 2nd solution is probably what will get implemented.
+For a high-performance main loop on Windows, use
+L{twisted.internet.iocpreactor.reactor.IOCPReactor}.
"""
-# System imports
+from __future__ import absolute_import, division
+
import time
import sys
+
from threading import Thread
from weakref import WeakKeyDictionary
@@ -70,9 +49,9 @@
import win32gui
-# Twisted imports
from twisted.internet import posixbase
from twisted.python import log, threadable, failure
+from twisted.python.compat import keys
from twisted.internet.interfaces import IReactorFDSet
from twisted.internet.interfaces import IReactorWin32Events
from twisted.internet.threads import blockingCallFromThread
@@ -177,7 +156,8 @@
def removeReader(self, reader):
- """Remove a Selectable for notification of data available to read.
+ """
+ Remove a Selectable for notification of data available to read.
"""
if reader in self._reads:
del self._events[self._reads[reader]]
@@ -191,7 +171,8 @@
def removeWriter(self, writer):
- """Remove a Selectable for notification of data available to write.
+ """
+ Remove a Selectable for notification of data available to write.
"""
if writer in self._writes:
del self._writes[writer]
@@ -205,11 +186,17 @@
def getReaders(self):
- return self._reads.keys()
+ """
+ Return a L{list} of all readers.
+ """
+ return keys(self._reads)
def getWriters(self):
- return self._writes.keys()
+ """
+ Return a L{list} of all writers.
+ """
+ return keys(self._writes)
def doWaitForMultipleEvents(self, timeout):
@@ -225,11 +212,11 @@
# If any descriptors are trying to close, try to get them out of the way
# first.
- for reader in self._closedAndReading.keys():
+ for reader in keys(self._closedAndReading):
ranUserCode = True
self._runAction('doRead', reader)
- for fd in self._writes.keys():
+ for fd in self.getWriters():
ranUserCode = True
log.callWithLogger(fd, self._runWrite, fd)
@@ -245,7 +232,7 @@
time.sleep(timeout)
return
- handles = self._events.keys() or [self.dummyEvent]
+ handles = keys(self._events) or [self.dummyEvent]
timeout = int(timeout * 1000)
val = MsgWaitForMultipleObjects(handles, 0, timeout, QS_ALLINPUT)
if val == WAIT_TIMEOUT:
Modified: branches/moar-windows-8025-7/twisted/logger/test/test_stdlib.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/logger/test/test_stdlib.py (original)
+++ branches/moar-windows-8025-7/twisted/logger/test/test_stdlib.py Thu Apr 14 20:22:18 2016
@@ -5,7 +5,10 @@
Test cases for L{twisted.logger._format}.
"""
+from __future__ import absolute_import, division
+
import sys
+
from io import BytesIO, TextIOWrapper
import logging as py_logging
from inspect import getsourcefile
@@ -236,7 +239,7 @@
stream = output
template = py_logging.BASIC_FORMAT
if _PY3:
- stream = TextIOWrapper(output, encoding="utf-8")
+ stream = TextIOWrapper(output, encoding="utf-8", newline="\n")
formatter = py_logging.Formatter(template)
handler = py_logging.StreamHandler(stream)
handler.setFormatter(formatter)
Modified: branches/moar-windows-8025-7/twisted/python/dist3.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/python/dist3.py (original)
+++ branches/moar-windows-8025-7/twisted/python/dist3.py Thu Apr 14 20:22:18 2016
@@ -65,12 +65,15 @@
"twisted.cred.test.__init__",
"twisted.internet.__init__",
"twisted.internet._baseprocess",
+ "twisted.internet._dumbwin32proc",
"twisted.internet._glibbase",
"twisted.internet._newtls",
+ "twisted.internet._pollingfile",
"twisted.internet._posixstdio",
"twisted.internet._posixserialport",
"twisted.internet._signals",
"twisted.internet._win32serialport",
+ "twisted.internet._win32stdio",
"twisted.internet.abstract",
"twisted.internet.address",
"twisted.internet.base",
@@ -106,6 +109,7 @@
"twisted.internet.udp",
"twisted.internet.unix",
"twisted.internet.utils",
+ "twisted.internet.win32eventreactor",
"twisted.logger.__init__",
"twisted.logger._buffer",
"twisted.logger._file",
@@ -213,6 +217,7 @@
"twisted.python.zippath",
"twisted.scripts.__init__",
"twisted.scripts._twistd_unix",
+ "twisted.scripts._twistw",
"twisted.scripts.trial",
"twisted.scripts.twistd",
"twisted.test.__init__",
@@ -298,6 +303,8 @@
"twisted.internet.test.test_kqueuereactor",
"twisted.internet.test.test_main",
"twisted.internet.test.test_newtls",
+ "twisted.internet.test.test_pollingfile",
+ "twisted.internet.test.test_win32events",
"twisted.internet.test.test_posixbase",
"twisted.internet.test.test_posixprocess",
"twisted.internet.test.test_process",
Modified: branches/moar-windows-8025-7/twisted/python/filepath.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/python/filepath.py (original)
+++ branches/moar-windows-8025-7/twisted/python/filepath.py Thu Apr 14 20:22:18 2016
@@ -1532,8 +1532,8 @@
finally:
f.close()
if platform.isWindows() and exists(self.path):
- os.unlink(self.path)
- os.rename(sib.path, self.path)
+ os.remove(self.path)
+ os.rename(sib.path, self.asBytesMode().path)
def __cmp__(self, other):
@@ -1708,7 +1708,8 @@
filesystems)
"""
try:
- os.rename(self.path, destination.path)
+ os.rename(self._getPathAsSameTypeAs(destination.path),
+ destination.path)
except OSError as ose:
if ose.errno == errno.EXDEV:
# man 2 rename, ubuntu linux 5.10 "breezy":
Modified: branches/moar-windows-8025-7/twisted/python/lockfile.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/python/lockfile.py (original)
+++ branches/moar-windows-8025-7/twisted/python/lockfile.py Thu Apr 14 20:22:18 2016
@@ -64,7 +64,7 @@
# For monkeypatching in tests
_open = open
-
+ from time import sleep as _sleep
def symlink(value, filename):
"""
@@ -87,6 +87,41 @@
f.write(value)
f.flush()
+ if _PY3:
+ readValue = ""
+ iterations = 0
+ # Python 3 has no 'commit' flag for fopen, so let Windows catch
+ # up... we do this by looping and reading the file, hoping to get
+ # the correct value. It sucks, but, what can you do? Locks are
+ # global state, and as we all know, global state is BAD and EVIL.
+ # NOT EVEN ONCE - Amber
+ while readValue != value:
+ with _open(newvalname, "r") as f:
+ readValue = f.read()
+
+ if readValue != value:
+ iterations += 1
+
+ # What is a reasonable number here? Well, you give an inch,
+ # and Windows takes a mile. Sleeping for a lot of time may
+ # waste time, but waiting for a small (0.001s) time takes
+ # far longer on 3.5. than the 0.001s you'd expect.
+ # 10 seconds seems like a reasonable amount of time,
+ # assuming that file I/O on Windows can be deathly slow.
+ if iterations > 100:
+ try:
+ # Try and remove the failed lock. We have given up
+ # at this point, so if we can't remove it, we
+ # can't really try much.
+ os.remove(newvalname)
+ except:
+ pass
+ # We ought to play sad_trombone.mp3 here. Give up and
+ # throw an exception.
+ raise RuntimeError("Unable to get a lock.")
+
+ _sleep(0.1)
+
try:
rename(newlinkname, filename)
except:
Modified: branches/moar-windows-8025-7/twisted/python/log.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/python/log.py (original)
+++ branches/moar-windows-8025-7/twisted/python/log.py Thu Apr 14 20:22:18 2016
@@ -554,7 +554,23 @@
}
msgStr = _safeFormat("[%(system)s] %(text)s\n", fmtDict)
- util.untilConcludes(self.write, timeStr + " " + msgStr)
+ if _PY3:
+ completedLine = timeStr + " " + msgStr
+
+ try:
+ util.untilConcludes(self.write, completedLine)
+ except UnicodeEncodeError:
+ # If we get a UnicodeDecodeError, we shouldn't really try
+ # guessing what the terminal is. Go ASCII, and if people
+ # don't like it, they should use twisted.logger.
+ completedLine = completedLine.encode(
+ 'ascii',
+ errors='backslashreplace')
+ util.untilConcludes(self.write,
+ completedLine.decode('ascii'))
+ else:
+ util.untilConcludes(self.write, timeStr + " " + msgStr)
+
util.untilConcludes(self.flush) # Hoorj!
Modified: branches/moar-windows-8025-7/twisted/python/test/test_deprecate.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/python/test/test_deprecate.py (original)
+++ branches/moar-windows-8025-7/twisted/python/test/test_deprecate.py Thu Apr 14 20:22:18 2016
@@ -26,7 +26,9 @@
deprecatedProperty,
)
+from twisted.python.compat import _PY3
from twisted.python.versions import Version
+from twisted.python.runtime import platform
from twisted.python.filepath import FilePath
from twisted.python.test import deprecatedattributes
@@ -391,6 +393,12 @@
self.addCleanup(
lambda: (sys.modules.clear(), sys.modules.update(modules)))
+ # On Windows on Python 3, most FilePath interactions produce
+ # DeprecationWarnings, so flush them here so that they don't interfere
+ # with the tests.
+ if platform.isWindows() and _PY3:
+ self.flushWarnings()
+
def test_warning(self):
"""
@@ -469,7 +477,7 @@
self.addCleanup(sys.modules.pop, module.__name__)
module.callTestFunction()
- warningsShown = self.flushWarnings()
+ warningsShown = self.flushWarnings([module.testFunction])
warnedPath = FilePath(warningsShown[0]["filename"].encode("utf-8"))
expectedPath = self.package.sibling(
b'twisted_renamed_helper').child(b'module.py')
Modified: branches/moar-windows-8025-7/twisted/python/zippath.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/python/zippath.py (original)
+++ branches/moar-windows-8025-7/twisted/python/zippath.py Thu Apr 14 20:22:18 2016
@@ -19,6 +19,7 @@
from twisted.python.compat import comparable, cmp
from twisted.python.filepath import IFilePath, FilePath, AbstractFilePath
from twisted.python.filepath import _coerceToFilesystemEncoding
+from twisted.python.filepath import UnlistableError
from zope.interface import implementer
@@ -128,9 +129,11 @@
if self.isdir():
return list(self.archive.childmap[self.pathInArchive].keys())
else:
- raise OSError(errno.ENOTDIR, "Leaf zip entry listed")
+ raise UnlistableError(
+ OSError(errno.ENOTDIR, "Leaf zip entry listed"))
else:
- raise OSError(errno.ENOENT, "Non-existent zip entry listed")
+ raise UnlistableError(
+ OSError(errno.ENOENT, "Non-existent zip entry listed"))
def splitext(self):
Modified: branches/moar-windows-8025-7/twisted/scripts/_twistw.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/scripts/_twistw.py (original)
+++ branches/moar-windows-8025-7/twisted/scripts/_twistw.py Thu Apr 14 20:22:18 2016
@@ -2,10 +2,14 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
+from __future__ import absolute_import, division, print_function
+
+import sys
+import os
+
from twisted.python import log
from twisted.application import app, service, internet
from twisted import copyright
-import sys, os
@@ -16,10 +20,11 @@
]
def opt_version(self):
- """Print version information and exit.
"""
- print 'twistd (the Twisted Windows runner) %s' % copyright.version
- print copyright.copyright
+ Print version information and exit.
+ """
+ print('twistd (the Twisted Windows runner) %s' % copyright.version)
+ print(copyright.copyright)
sys.exit()
@@ -45,6 +50,6 @@
"""
service.IService(self.application).privilegedStartService()
app.startApplication(self.application, not self.config['no_save'])
- app.startApplication(internet.TimerService(0.1, lambda:None), 0)
+ app.startApplication(internet.TimerService(0.1, lambda: None), 0)
self.startReactor(None, self.oldstdout, self.oldstderr)
log.msg("Server Shut Down.")
Modified: branches/moar-windows-8025-7/twisted/scripts/trial.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/scripts/trial.py (original)
+++ branches/moar-windows-8025-7/twisted/scripts/trial.py Thu Apr 14 20:22:18 2016
@@ -527,13 +527,17 @@
namedModule('readline')
except ImportError:
print("readline module not available")
- sys.exc_clear()
+ if hasattr(sys, "exc_clear"):
+ # exc_clear is only available on Python 2
+ sys.exc_clear()
for path in ('.pdbrc', 'pdbrc'):
if os.path.exists(path):
try:
rcFile = file(path, 'r')
except IOError:
- sys.exc_clear()
+ if hasattr(sys, "exc_clear"):
+ # exc_clear is only available on Python 2
+ sys.exc_clear()
else:
dbg.rcLines.extend(rcFile.readlines())
return dbg
Modified: branches/moar-windows-8025-7/twisted/test/process_stdinreader.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/test/process_stdinreader.py (original)
+++ branches/moar-windows-8025-7/twisted/test/process_stdinreader.py Thu Apr 14 20:22:18 2016
@@ -1,23 +1,38 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
-"""Script used by twisted.test.test_process on win32."""
+"""
+Script used by twisted.test.test_process on win32.
+"""
+
+from __future__ import absolute_import, division
import sys, os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
-
-sys.stdout.write("out\n")
-sys.stdout.flush()
-sys.stderr.write("err\n")
-sys.stderr.flush()
+# We want to write bytes directly to the output, not text, because otherwise
+# newlines get mangled. Get the buffer if it is available.
+if hasattr(sys.stdout, "buffer"):
+ stdout = sys.stdout.buffer
+else:
+ stdout = sys.stdout
+
+if hasattr(sys.stderr, "buffer"):
+ stderr = sys.stderr.buffer
+else:
+ stderr = sys.stderr
+
+stdout.write(b"out\n")
+stdout.flush()
+stderr.write(b"err\n")
+stderr.flush()
data = sys.stdin.read()
-sys.stdout.write(data)
-sys.stdout.write("\nout\n")
-sys.stderr.write("err\n")
+stdout.write(data.encode('ascii'))
+stdout.write(b"\nout\n")
+stderr.write(b"err\n")
sys.stdout.flush()
sys.stderr.flush()
Modified: branches/moar-windows-8025-7/twisted/test/test_compat.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/test/test_compat.py (original)
+++ branches/moar-windows-8025-7/twisted/test/test_compat.py Thu Apr 14 20:22:18 2016
@@ -1,7 +1,6 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
-
"""
Tests for L{twisted.python.compat}.
"""
@@ -18,6 +17,7 @@
iterbytes, intToBytes, ioType, bytesEnviron, iteritems
)
from twisted.python.filepath import FilePath
+from twisted.python.runtime import platform
@@ -751,6 +751,9 @@
self.assertEqual(list(types), [bytes])
+ if platform.isWindows():
+ test_alwaysBytes.skip = "Environment vars are always str on Windows."
+
class OrderedDictTests(unittest.TestCase):
Modified: branches/moar-windows-8025-7/twisted/test/test_internet.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/test/test_internet.py (original)
+++ branches/moar-windows-8025-7/twisted/test/test_internet.py Thu Apr 14 20:22:18 2016
@@ -957,23 +957,28 @@
-resolve_helper = """
-from __future__ import print_function
+resolve_helper = r"""
import %(reactor)s
%(reactor)s.install()
from twisted.internet import reactor
-class Foo:
+import sys
+if hasattr(sys.stdout, "buffer"):
+ output = sys.stdout.buffer
+else:
+ output = sys.stdout
+
+class Foo(object):
def __init__(self):
reactor.callWhenRunning(self.start)
self.timer = reactor.callLater(3, self.failed)
def start(self):
reactor.resolve('localhost').addBoth(self.done)
def done(self, res):
- print('done', res)
+ output.write(('done ' + res + '\n').encode('ascii'))
reactor.stop()
def failed(self):
- print('failed')
+ output.write('failed\n')
self.timer = None
reactor.stop()
f = Foo()
Modified: branches/moar-windows-8025-7/twisted/test/test_lockfile.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/test/test_lockfile.py (original)
+++ branches/moar-windows-8025-7/twisted/test/test_lockfile.py Thu Apr 14 20:22:18 2016
@@ -13,6 +13,7 @@
from twisted.trial import unittest
from twisted.python import lockfile
+from twisted.python.compat import _PY3
from twisted.python.reflect import requireModule
from twisted.python.runtime import platform
@@ -24,6 +25,8 @@
skipKill = ("On windows, lockfile.kill is not implemented in the "
"absence of win32api and/or pywintypes.")
+
+
class UtilTests(unittest.TestCase):
"""
Tests for the helper functions used to implement L{FilesystemLock}.
@@ -91,6 +94,54 @@
"Windows.")
+ def test_symlinkLockTimeoutWindows(self):
+ """
+ L{lockfile.symlink} on Python 3 on Windows cannot get an 'atomic' lock.
+ So, we have to fake it, and just loop until we have acquired it. If we
+ never get the correct value, we timeout.
+ """
+ name = self.mktemp()
+ class FakeOpen(object):
+ """
+ A fake open() for testing, that never returns any content and
+ throws away any writes.
+ """
+ def __init__(self, name, mode):
+ pass
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ pass
+
+ def write(self, data):
+ pass
+
+ def flush(self):
+ pass
+
+ def close(self):
+ pass
+
+ def read(self):
+ return ""
+
+ sleptFor = []
+
+ def fakeSleep(time):
+ sleptFor.append(time)
+
+ self.patch(lockfile, '_open', FakeOpen)
+ self.patch(lockfile, '_sleep', fakeSleep)
+ self.assertRaises(RuntimeError, lockfile.symlink, name, 'data')
+ self.assertEqual(round(sum(sleptFor)), 10.0)
+ if not (platform.isWindows() and _PY3):
+ test_symlinkLockTimeoutWindows.skip = (
+ "The interesting(tm) symlink timeout support is only needed on "
+ "Windows on Python 3.")
+
+
def test_kill(self):
"""
L{lockfile.kill} returns without error if passed the PID of a
Modified: branches/moar-windows-8025-7/twisted/test/test_paths.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/test/test_paths.py (original)
+++ branches/moar-windows-8025-7/twisted/test/test_paths.py Thu Apr 14 20:22:18 2016
@@ -283,6 +283,9 @@
self.assertRaises(filepath.UnlistableError, fwp.children)
self.assertRaises(WindowsError, fwp.children)
+ if _PY3:
+ test_windowsErrorExcept.skip = "This doesn't raise WindowsError anymore"
+
def test_alwaysCatchOSError(self):
"""
Modified: branches/moar-windows-8025-7/twisted/test/test_process.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/test/test_process.py (original)
+++ branches/moar-windows-8025-7/twisted/test/test_process.py Thu Apr 14 20:22:18 2016
@@ -40,7 +40,7 @@
from twisted.python.log import msg
from twisted.internet import reactor, protocol, error, interfaces, defer
from twisted.trial import unittest
-from twisted.python import util, runtime, procutils
+from twisted.python import runtime, procutils
from twisted.python.compat import _PY3, networkString, xrange
from twisted.python.filepath import FilePath, _asFilesystemBytes
@@ -2245,8 +2245,8 @@
p.transport.closeStdin()
def processEnded(ign):
- self.assertEqual(p.errF.getvalue(), "err\nerr\n")
- self.assertEqual(p.outF.getvalue(), "out\nhello, world\nout\n")
+ self.assertEqual(p.errF.getvalue(), b"err\nerr\n")
+ self.assertEqual(p.outF.getvalue(), b"out\nhello, world\nout\n")
return d.addCallback(processEnded)
@@ -2386,11 +2386,14 @@
from twisted.internet import _dumbwin32proc
from twisted.test import mock_win32process
self.patch(_dumbwin32proc, "win32process", mock_win32process)
- scriptPath = util.sibpath(__file__, "process_cmdline.py")
+ scriptPath = FilePath(__file__).sibling(b"process_cmdline.py").path
d = defer.Deferred()
processProto = TrivialProcessProtocol(d)
- comspec = bytes(os.environ["COMSPEC"])
+ if _PY3:
+ comspec = os.environ["COMSPEC"].encode("mbcs")
+ else:
+ comspec = str(os.environ["COMSPEC"])
cmd = [comspec, b"/c", pyExe, scriptPath]
p = _dumbwin32proc.Process(reactor,
@@ -2582,8 +2585,11 @@
"""
d = self.doit(1)
def _check(errput):
- if _PY3:
+ if _PY3 and not runtime.platform.isWindows():
self.assertIn(b'BrokenPipeError', errput)
+ elif _PY3:
+ self.assertIn(b"OSError", errput)
+ self.assertIn(b"22", errput)
else:
self.assertIn(b'OSError', errput)
if runtime.platform.getType() != 'win32':
Modified: branches/moar-windows-8025-7/twisted/test/test_tcp.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/test/test_tcp.py (original)
+++ branches/moar-windows-8025-7/twisted/test/test_tcp.py Thu Apr 14 20:22:18 2016
@@ -14,6 +14,8 @@
from twisted.trial import unittest
+from twisted.python.compat import _PY3
+from twisted.python.runtime import platform
from twisted.python.log import msg, err
from twisted.internet import protocol, reactor, defer, interfaces
from twisted.internet import error
@@ -22,6 +24,8 @@
from twisted.protocols import policies
from twisted.test.proto_helpers import AccumulatingProtocol
+WSAENOTSOCK = 10038
+
def loopUntil(predicate, interval=0):
"""
@@ -906,7 +910,8 @@
expected = b"".join([b"Hello Cleveland!\n",
b"Goodbye", b" cruel", b" world", b"\n"])
self.assertTrue(clientF.data == expected,
- "client didn't receive all the data it expected")
+ "client didn't receive all the data it expected"
+ "(%s!=%s)" % (clientF.data, expected))
d = defer.gatherResults([wrappedF.onDisconnect,
wrappedClientF.onDisconnect])
return d.addCallback(check)
@@ -1138,11 +1143,18 @@
Return the errno expected to result from writing to a closed
platform socket handle.
"""
- # These platforms have been seen to give EBADF:
- #
- # Linux 2.4.26, Linux 2.6.15, OS X 10.4, FreeBSD 5.4
- # Windows 2000 SP 4, Windows XP SP 2
- return errno.EBADF
+ if _PY3 and platform.isWindows():
+ # These platforms have been seen to give WinError 10038
+ #
+ # Windows 10 on Python 3.4/3.5
+ return WSAENOTSOCK
+ else:
+ # These platforms have been seen to give EBADF:
+ #
+ # Linux 2.4.26, Linux 2.6.15, OS X 10.4, FreeBSD 5.4
+ # Windows 2000 SP 4, Windows XP SP 2
+ return errno.EBADF
+
def test_properlyCloseFiles(self):
@@ -1363,12 +1375,16 @@
self.factory.done = 1
self.transport.loseConnection()
+
+
class LargeBufferReaderProtocol(protocol.Protocol):
def dataReceived(self, data):
self.factory.len += len(data)
def connectionLost(self, reason):
self.factory.done = 1
+
+
class LargeBufferReaderClientFactory(protocol.ClientFactory):
def __init__(self):
self.done = 0
@@ -1380,8 +1396,10 @@
return p
+
class FireOnClose(policies.ProtocolWrapper):
- """A wrapper around a protocol that makes it fire a deferred when
+ """
+ A wrapper around a protocol that makes it fire a deferred when
connectionLost is called.
"""
def connectionLost(self, reason):
@@ -1389,6 +1407,7 @@
self.factory.deferred.callback(None)
+
class FireOnCloseFactory(policies.WrappingFactory):
protocol = FireOnClose
@@ -1398,10 +1417,12 @@
class LargeBufferTests(unittest.TestCase):
- """Test that buffering large amounts of data works.
+ """
+ Test that buffering large amounts of data works.
"""
datalen = 60*1024*1024
+
def testWriter(self):
f = protocol.Factory()
f.protocol = LargeBufferWriterProtocol
@@ -1427,10 +1448,10 @@
return d.addCallback(check)
+
@implementer(IHalfCloseableProtocol)
class MyHCProtocol(AccumulatingProtocol):
-
readHalfClosed = False
writeHalfClosed = False
@@ -1447,6 +1468,7 @@
self.connectionLost(None)
+
class MyHCFactory(protocol.ServerFactory):
called = 0
Modified: branches/moar-windows-8025-7/twisted/trial/test/test_runner.py
==============================================================================
--- branches/moar-windows-8025-7/twisted/trial/test/test_runner.py (original)
+++ branches/moar-windows-8025-7/twisted/trial/test/test_runner.py Thu Apr 14 20:22:18 2016
@@ -1030,11 +1030,16 @@
# We have to use a pyunit test, otherwise we'll get deprecation
# warnings about using iterate() in a test.
trialRunner.run(pyunit.TestCase('id'))
- self.assertWarns(
- DeprecationWarning,
+
+ f()
+ warnings = self.flushWarnings([self.test_reporterDeprecations])
+
+ self.assertEqual(warnings[0]['category'], DeprecationWarning)
+ self.assertEqual(warnings[0]['message'],
"%s should implement done() but doesn't. Falling back to "
- "printErrors() and friends." % reflect.qual(result.__class__),
- __file__, f)
+ "printErrors() and friends." % reflect.qual(result.__class__))
+ self.assertEqual(warnings[0]['filename'], __file__)
+ self.assertEqual(len(warnings), 1)