/usr/share/pyshared/meliae/files.py is in python-meliae 0.4.0-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | # Copyright (C) 2009, 2010 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Work with files on disk."""
import errno
import gzip
try:
import multiprocessing
except ImportError:
multiprocessing = None
import subprocess
import sys
def open_file(filename):
"""Open a file which might be a regular file or a gzip.
:return: An iterator of lines, and a cleanup function.
"""
source = open(filename, 'rb')
gzip_source = gzip.GzipFile(mode='rb', fileobj=source)
try:
line = gzip_source.readline()
except KeyboardInterrupt:
raise
except:
# probably not a gzip file
source.seek(0)
return source, None
else:
# We don't need these anymore, so close them out in case the rest of
# the code raises an exception.
gzip_source.close()
source.close()
# a gzip file
# preference - a gzip subprocess
if sys.platform == 'win32':
close_fds = False # not supported
else:
close_fds = True
try:
process = subprocess.Popen(['gzip', '-d', '-c', filename],
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, close_fds=close_fds)
except OSError, e:
if e.errno == errno.ENOENT:
# failing that, use another python process
return _open_mprocess(filename)
# make reading from stdin, or writting errors cause immediate aborts
process.stdin.close()
process.stderr.close()
terminate = getattr(process, 'terminate', None)
# terminate is a py2.6 thing
if terminate is not None:
def terminate_or_pass():
# It seems that on windows, sometimes terminate() can raise
# WindowsError: [Error 5] Access is denied
# My guess is that the process has actually completed, and is
# no longer running.
try:
return terminate()
except OSError, e:
sys.stderr.write('Ignoring failure to terminate process:'
' %s\n' % (e,))
# We *could* check if process.poll() returns that the
# process has already exited, etc.
return process.stdout, terminate_or_pass
else:
# We would like to use process.wait() but that can cause a deadlock
# if the child is still writing.
# The other alternative is process.communicate, but we closed
# stderr, and communicate wants to read from it. (We get:
# ValueError: I/O operation on closed file
# if we try it here. Also, for large files, this may be many GB
# worth of data.
# So for now, live with the deadlock...
return process.stdout, process.wait
def _stream_file(filename, child):
gzip_source = gzip.GzipFile(filename, 'rb')
for line in gzip_source:
child.send(line)
child.send(None)
def _open_mprocess(filename):
if multiprocessing is None:
# can't multiprocess, use inprocess gzip.
return gzip.GzipFile(filename, mode='rb'), None
parent, child = multiprocessing.Pipe(False)
process = multiprocessing.Process(target=_stream_file, args=(filename, child))
process.start()
def iter_pipe():
while True:
line = parent.recv()
if line is None:
break
yield line
return iter_pipe(), process.join
|