def nextfile(self):
savestdout = self._savestdout
-- self._savestdout = 0
++ self._savestdout = None
if savestdout:
sys.stdout = savestdout
output = self._output
-- self._output = 0
- if output:
- output.close()
-
- file = self._file
- self._file = 0
- if file and not self._isstdin:
- file.close()
-
- backupfilename = self._backupfilename
- self._backupfilename = 0
- if backupfilename and not self._backup:
- try: os.unlink(backupfilename)
- except OSError: pass
-
- self._isstdin = False
- self._buffer = []
- self._bufindex = 0
++ self._output = None
+ try:
+ if output:
+ output.close()
+ finally:
+ file = self._file
- self._file = 0
++ self._file = None
+ try:
+ if file and not self._isstdin:
+ file.close()
+ finally:
+ backupfilename = self._backupfilename
- self._backupfilename = 0
++ self._backupfilename = None
+ if backupfilename and not self._backup:
+ try: os.unlink(backupfilename)
+ except OSError: pass
+
+ self._isstdin = False
+ self._buffer = []
+ self._bufindex = 0
def readline(self):
try:
def close(self):
"""Close the file."""
if hasattr(self, '_file'):
-- if hasattr(self._file, 'close'):
-- self._file.close()
-- del self._file
++ try:
++ if hasattr(self._file, 'close'):
++ self._file.close()
++ finally:
++ del self._file
def _read(self, size, read_method):
"""Read size bytes using read_method."""
return ready
def close(self):
- self._epoll.close()
- super().close()
+ try:
+ self._epoll.close()
+ finally:
+ super().close()
- self._devpoll.close()
- super().close()
+if hasattr(select, 'devpoll'):
+
+ class DevpollSelector(_BaseSelectorImpl):
+ """Solaris /dev/poll selector."""
+
+ def __init__(self):
+ super().__init__()
+ self._devpoll = select.devpoll()
+
+ def fileno(self):
+ return self._devpoll.fileno()
+
+ def register(self, fileobj, events, data=None):
+ key = super().register(fileobj, events, data)
+ poll_events = 0
+ if events & EVENT_READ:
+ poll_events |= select.POLLIN
+ if events & EVENT_WRITE:
+ poll_events |= select.POLLOUT
+ self._devpoll.register(key.fd, poll_events)
+ return key
+
+ def unregister(self, fileobj):
+ key = super().unregister(fileobj)
+ self._devpoll.unregister(key.fd)
+ return key
+
+ def select(self, timeout=None):
+ if timeout is None:
+ timeout = None
+ elif timeout <= 0:
+ timeout = 0
+ else:
+ # devpoll() has a resolution of 1 millisecond, round away from
+ # zero to wait *at least* timeout seconds.
+ timeout = math.ceil(timeout * 1e3)
+
+ fd_event_list = self._devpoll.poll(timeout)
+
+ ready = []
+ for fd, event in fd_event_list:
+ events = 0
+ if event & ~select.POLLIN:
+ events |= EVENT_WRITE
+ if event & ~select.POLLOUT:
+ events |= EVENT_READ
+
+ key = self._key_from_fd(fd)
+ if key:
+ ready.append((key, events & key.events))
+ return ready
+
+ def close(self):
++ try:
++ self._devpoll.close()
++ finally:
++ super().close()
+
+
if hasattr(select, 'kqueue'):
class KqueueSelector(_BaseSelectorImpl):
return ready
def close(self):
- self._kqueue.close()
- super().close()
+ try:
+ self._kqueue.close()
+ finally:
+ super().close()
-# Choose the best implementation: roughly, epoll|kqueue > poll > select.
+# Choose the best implementation, roughly:
+# epoll|kqueue|devpoll > poll > select.
# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
if 'KqueueSelector' in globals():
DefaultSelector = KqueueSelector
def close(self):
"""Close the connection."""
- if self.sock:
- self.sock.close()
- self.sock = 0
- self.eof = 1
+ sock = self.sock
- self.sock = 0
- self.eof = 1
++ self.sock = None
++ self.eof = True
self.iacseq = b''
self.sb = 0
+ if sock:
+ sock.close()
def get_socket(self):
"""Return the socket object used internally."""
self._err_handler.fatalError(exc)
def close(self):
- if self._entity_stack:
+ if self._entity_stack or self._parser is None:
# If we are completing an external entity, do nothing here
return
- self.feed("", isFinal = 1)
- self._cont_handler.endDocument()
- self._parsing = 0
- # break cycle created by expat handlers pointing to our methods
- self._parser = None
try:
- file = self._source.getCharacterStream()
- if file is not None:
- file.close()
+ self.feed("", isFinal = 1)
+ self._cont_handler.endDocument()
finally:
- file = self._source.getByteStream()
- if file is not None:
- file.close()
+ self._parsing = 0
+ # break cycle created by expat handlers pointing to our methods
+ self._parser = None
- bs = self._source.getByteStream()
- if bs is not None:
- bs.close()
++ try:
++ file = self._source.getCharacterStream()
++ if file is not None:
++ file.close()
++ finally:
++ file = self._source.getByteStream()
++ if file is not None:
++ file.close()
def _reset_cont_handler(self):
self._parser.ProcessingInstructionHandler = \
Library
-------
+ - Issue #23865: close() methods in multiple modules now are idempotent and more
+ robust at shutdown. If needs to release multiple resources, they are released
+ even if errors are occured.
+
+- Issue #23400: Raise same exception on both Python 2 and 3 if sem_open is not
+ available. Patch by Davin Potts.
+
+- Issue #10838: The subprocess now module includes SubprocessError and
+ TimeoutError in its list of exported names for the users wild enough
+ to use "from subprocess import *".
+
+- Issue #23411: Added DefragResult, ParseResult, SplitResult, DefragResultBytes,
+ ParseResultBytes, and SplitResultBytes to urllib.parse.__all__.
+ Patch by Martin Panter.
+
- Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if
the FTP connection failed to fix a ResourceWarning.