4
4
# --- BEGIN_HEADER ---
5
5
#
6
6
# fileio - wrappers to keep file I/O in a single replaceable module
7
- # Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
7
+ # Copyright (C) 2003-2024 The MiG Project by the Science HPC Center at UCPH
8
8
#
9
9
# This file is part of MiG.
10
10
#
70
70
exit (1 )
71
71
72
72
73
- def write_chunk (path , chunk , offset , logger , mode = 'r+b' ):
74
- """Wrapper to handle writing of chunks with offset to path.
75
- Creates file first if it doesn't already exist.
73
+ def _write_chunk (path , chunk , offset , logger = None , mode = 'r+b' ,
74
+ make_parent = True , create_file = True ):
75
+ """Internal helper to wrap writing of chunks with offset to path.
76
+ The optional make_parent and create_file are used to decide if the parent
77
+ directory and the file should be created if it doesn't already exist.
76
78
"""
77
79
if not logger :
78
80
logger = null_logger ("dummy" )
@@ -81,66 +83,70 @@ def write_chunk(path, chunk, offset, logger, mode='r+b'):
81
83
# create dir and file if it does not exists
82
84
83
85
(head , _ ) = os .path .split (path )
84
- if not os .path .isdir (head ):
86
+ if not os .path .isdir (head ) and make_parent :
85
87
try :
86
88
os .mkdir (head )
87
89
except Exception as err :
88
90
logger .error ("could not create parent dir %r: %s" % (head , err ))
89
- if not os .path .isfile (path ):
91
+ return False
92
+
93
+ # ensure a file is present
94
+
95
+ if not os .path .isfile (path ) and create_file :
90
96
try :
91
97
open (path , "w" ).close ()
92
98
except Exception as err :
93
99
logger .error ("could not create file %r: %s" % (path , err ))
100
+ return False
101
+
94
102
try :
95
- filehandle = open (path , mode )
96
- # Make sure we can write at requested position, filling if needed
97
- try :
98
- filehandle . seek ( offset )
99
- except :
100
- filehandle . seek ( 0 , 2 )
101
- file_size = filehandle .tell ( )
102
- for _ in xrange ( offset - file_size ):
103
- filehandle . write ( ' \0 ' )
104
- # logger.debug("write %r chunk of size %d at position %d" %
105
- # (path, len(chunk), filehandle.tell()))
106
- filehandle .write ( chunk )
107
- filehandle .close ( )
108
- # logger.debug("file %r chunk written at %d" % (path, offset))
109
- return True
103
+ with open (path , mode ) as filehandle :
104
+ if offset > 0 :
105
+ # Make sure we can write at requested position, filling if needed
106
+ try :
107
+ filehandle . seek ( offset )
108
+ except :
109
+ filehandle .seek ( 0 , 2 )
110
+ file_size = filehandle . tell ()
111
+ for _ in xrange ( offset - file_size ):
112
+ filehandle . write ( ' \0 ' )
113
+ # logger.debug("write %r chunk of size %d at position %d" %
114
+ # (path, len(chunk), filehandle.tell()) )
115
+ filehandle .write ( chunk )
116
+ # logger.debug("file %r chunk written at %d" % (path, offset))
117
+ return True
110
118
except Exception as err :
111
119
logger .error ("could not write %r chunk at %d: %s" %
112
120
(path , offset , err ))
113
121
return False
114
122
115
123
124
+ def write_chunk (path , chunk , offset , logger , mode = 'r+b' ):
125
+ """Wrapper to handle writing of chunks with offset to path.
126
+ Creates file first if it doesn't already exist.
127
+ """
128
+ return _write_chunk (path , chunk , offset , logger , mode )
129
+
130
+
116
131
def write_file (content , path , logger , mode = 'w' , make_parent = True , umask = None ):
117
132
"""Wrapper to handle writing of contents to path"""
118
133
if not logger :
119
134
logger = null_logger ("dummy" )
120
135
# logger.debug("writing %r file" % path)
121
136
122
- # create dir if it does not exists
123
-
124
- (head , _ ) = os .path .split (path )
125
137
if umask is not None :
126
138
old_umask = os .umask (umask )
127
- if not os .path .isdir (head ) and make_parent :
128
- try :
129
- # logger.debug("making parent directory %r" % head)
130
- os .mkdir (head )
131
- except Exception as err :
132
- logger .error ("could not create parent dir %r: %s" % (head , err ))
133
- try :
134
- filehandle = open (path , mode )
135
- filehandle .write (content )
136
- filehandle .close ()
137
- # logger.debug("file %r written" % path)
138
- retval = True
139
- except Exception as err :
140
- logger .error ("could not write file %r: %s" % (path , err ))
141
- retval = False
139
+
140
+ # NOTE: detect byte writes and handle explicitly in a portable way
141
+ if isinstance (content , bytes ) and 'b' not in mode :
142
+ mode = "%sb" % mode # appended to avoid mode ordering error on PY2
143
+
144
+ retval = _write_chunk (path , content , offset = 0 , logger = logger , mode = mode ,
145
+ make_parent = make_parent , create_file = False )
146
+
142
147
if umask is not None :
143
148
os .umask (old_umask )
149
+
144
150
return retval
145
151
146
152
0 commit comments