cdxcore 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cdxcore might be problematic. Click here for more details.
- cdxcore/__init__.py +15 -0
- cdxcore/config.py +1633 -0
- cdxcore/crman.py +105 -0
- cdxcore/deferred.py +220 -0
- cdxcore/dynaplot.py +1155 -0
- cdxcore/filelock.py +430 -0
- cdxcore/jcpool.py +411 -0
- cdxcore/logger.py +319 -0
- cdxcore/np.py +1098 -0
- cdxcore/npio.py +270 -0
- cdxcore/prettydict.py +388 -0
- cdxcore/prettyobject.py +64 -0
- cdxcore/sharedarray.py +285 -0
- cdxcore/subdir.py +2963 -0
- cdxcore/uniquehash.py +970 -0
- cdxcore/util.py +1041 -0
- cdxcore/verbose.py +403 -0
- cdxcore/version.py +402 -0
- cdxcore-0.1.5.dist-info/METADATA +1418 -0
- cdxcore-0.1.5.dist-info/RECORD +30 -0
- cdxcore-0.1.5.dist-info/WHEEL +5 -0
- cdxcore-0.1.5.dist-info/licenses/LICENSE +21 -0
- cdxcore-0.1.5.dist-info/top_level.txt +4 -0
- conda/conda_exists.py +10 -0
- conda/conda_modify_yaml.py +42 -0
- tests/_cdxbasics.py +1086 -0
- tests/test_uniquehash.py +469 -0
- tests/test_util.py +329 -0
- up/git_message.py +7 -0
- up/pip_modify_setup.py +55 -0
cdxcore/filelock.py
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
"""
|
|
2
|
+
subdir
|
|
3
|
+
Simple class to keep track of directory sturctures and for automated caching on disk
|
|
4
|
+
Hans Buehler 2020
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .logger import Logger
|
|
8
|
+
from .verbose import Context
|
|
9
|
+
from .util import datetime, fmt_datetime, fmt_seconds
|
|
10
|
+
from .subdir import SubDir
|
|
11
|
+
_log = Logger(__file__)
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import os.path
|
|
15
|
+
import time
|
|
16
|
+
import platform as platform
|
|
17
|
+
|
|
18
|
+
IS_WINDOWS = platform.system()[0] == "W"
|
|
19
|
+
|
|
20
|
+
if IS_WINDOWS:
|
|
21
|
+
# http://timgolden.me.uk/pywin32-docs/Windows_NT_Files_.2d.2d_Locking.html
|
|
22
|
+
# need to install pywin32
|
|
23
|
+
try:
|
|
24
|
+
import win32file as win32file
|
|
25
|
+
except Exception as e:
|
|
26
|
+
raise ModuleNotFoundError("pywin32") from e
|
|
27
|
+
|
|
28
|
+
import win32con
|
|
29
|
+
import pywintypes
|
|
30
|
+
import win32security
|
|
31
|
+
import win32api
|
|
32
|
+
WIN_HIGHBITS=0xffff0000 #high-order 32 bits of byte range to lock
|
|
33
|
+
|
|
34
|
+
else:
|
|
35
|
+
win32file = None
|
|
36
|
+
|
|
37
|
+
import os
|
|
38
|
+
|
|
39
|
+
class FileLock(object):
|
|
40
|
+
"""
|
|
41
|
+
Systemwide Lock (Mutex) using files
|
|
42
|
+
https://code.activestate.com/recipes/519626-simple-file-based-mutex-for-very-basic-ipc/
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
__LOCK_ID = 0
|
|
46
|
+
|
|
47
|
+
def __init__(self, filename, * ,
|
|
48
|
+
acquire : bool = False,
|
|
49
|
+
release_on_exit : bool = True,
|
|
50
|
+
wait : bool = True,
|
|
51
|
+
timeout_seconds : int = None,
|
|
52
|
+
timeout_retry : int = None,
|
|
53
|
+
raise_on_fail : bool = True,
|
|
54
|
+
verbose : Context = Context.quiet ):
|
|
55
|
+
"""
|
|
56
|
+
Initialize new lock with name 'filename'
|
|
57
|
+
Acquire the lock if 'acquire' is True
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
filename :
|
|
62
|
+
Filename of the lock.
|
|
63
|
+
'filename' may start with '!/' to refer to the temp directory, or '~/' to refer to the user directory.
|
|
64
|
+
On Unix /dev/shm/ can be used to refer to shared memory.
|
|
65
|
+
acquire :
|
|
66
|
+
Whether to attempt aquiring the lock upon initialization
|
|
67
|
+
release_on_exit :
|
|
68
|
+
Whether to auto-release the lock upon exit.
|
|
69
|
+
wait :
|
|
70
|
+
If False, return immediately if the lock cannot be acquired.
|
|
71
|
+
If True, wait with below parameters; in particular if these are left as defaults the lock will wait indefinitely.
|
|
72
|
+
timeout_seconds :
|
|
73
|
+
Number of seconds to wait before retrying.
|
|
74
|
+
Set to 0 to fail immediately.
|
|
75
|
+
If set to None, then its value will depend on 'wait'.
|
|
76
|
+
If wait is True, then timeout_seconds==1; if wait is False, then timeout_seconds==0
|
|
77
|
+
timeout_retry :
|
|
78
|
+
How many times to retry before timing out.
|
|
79
|
+
Set to None to retry indefinitely.
|
|
80
|
+
raise_on_fail :
|
|
81
|
+
If the constructor fails to obtain the lock, raise an Exception:
|
|
82
|
+
This will be either of type
|
|
83
|
+
TimeoutError if 'timeout_seconds' > 0 and 'wait' is True, or
|
|
84
|
+
BlockingIOError if 'timeout_seconds' == 0 or 'wait' is False.
|
|
85
|
+
verbose :
|
|
86
|
+
Context which will print out operating information of the lock. This is helpful for debugging.
|
|
87
|
+
In particular, it will track __del__() function calls.
|
|
88
|
+
Set to None to print all context.
|
|
89
|
+
|
|
90
|
+
Exceptions
|
|
91
|
+
----------
|
|
92
|
+
If acquire is True, then this constructor may raise an exception:
|
|
93
|
+
TimeoutError if 'timeout_seconds' > 0 and 'wait' is True, or
|
|
94
|
+
BlockingIOError if 'timeout_seconds' == 0 or 'wait' is False.
|
|
95
|
+
"""
|
|
96
|
+
self._filename = SubDir.expandStandardRoot(filename)
|
|
97
|
+
self._fd = None
|
|
98
|
+
self._pid = os.getpid()
|
|
99
|
+
self._cnt = 0
|
|
100
|
+
self._lid = "LOCK" + fmt_datetime(datetime.datetime.now()) + (",%03ld:" % FileLock.__LOCK_ID) + filename
|
|
101
|
+
self.verbose = verbose if not verbose is None else Context(None)
|
|
102
|
+
self.release_on_exit = release_on_exit
|
|
103
|
+
FileLock.__LOCK_ID +=1
|
|
104
|
+
|
|
105
|
+
if acquire: self.acquire( wait=wait,
|
|
106
|
+
timeout_seconds=timeout_seconds,
|
|
107
|
+
timeout_retry=timeout_retry,
|
|
108
|
+
raise_on_fail=raise_on_fail )
|
|
109
|
+
|
|
110
|
+
def __del__(self):#NOQA
|
|
111
|
+
if self.release_on_exit and not self._fd is None:
|
|
112
|
+
self.verbose.write("%s: deleting locked object", self._lid)
|
|
113
|
+
self.release( force=True )
|
|
114
|
+
self._filename = None
|
|
115
|
+
|
|
116
|
+
def __str__(self) -> str:
|
|
117
|
+
""" Returns the current file name and the number of locks """
|
|
118
|
+
return "{%s:%ld}" % (self._filename, self._cnt)
|
|
119
|
+
|
|
120
|
+
def __bool__(self) -> bool:
|
|
121
|
+
""" Whether the lock is held """
|
|
122
|
+
return self.locked
|
|
123
|
+
@property
|
|
124
|
+
def num_acquisitions(self) -> int:
|
|
125
|
+
""" Return number of times acquire() was called. Zero if the lock is not held """
|
|
126
|
+
return self._cnt
|
|
127
|
+
@property
|
|
128
|
+
def locked(self) -> bool:
|
|
129
|
+
""" Returns True if the current object owns the lock """
|
|
130
|
+
return self._cnt > 0
|
|
131
|
+
@property
|
|
132
|
+
def filename(self) -> str:
|
|
133
|
+
""" Return filename """
|
|
134
|
+
return self._filename
|
|
135
|
+
|
|
136
|
+
def acquire(self, wait = True,
|
|
137
|
+
*, timeout_seconds : int = 1,
|
|
138
|
+
timeout_retry : int = 5,
|
|
139
|
+
raise_on_fail : bool = True) -> int:
|
|
140
|
+
"""
|
|
141
|
+
Acquire lock
|
|
142
|
+
|
|
143
|
+
Parameters
|
|
144
|
+
----------
|
|
145
|
+
wait :
|
|
146
|
+
If False, return immediately if the lock cannot be acquired.
|
|
147
|
+
If True, wait with below parameters
|
|
148
|
+
timeout_seconds :
|
|
149
|
+
Number of seconds to wait before retrying. If wait is False, this must be zero.
|
|
150
|
+
Set to 0 to fail immediately.
|
|
151
|
+
If set to None, then its value will depend on 'wait':
|
|
152
|
+
If wait is True, then timeout_seconds==1; if wait is False, then timeout_seconds==0
|
|
153
|
+
timeout_retry :
|
|
154
|
+
How many times to retry before timing out.
|
|
155
|
+
Set to zero to try ony once.
|
|
156
|
+
Set to None to retry indefinitely.
|
|
157
|
+
raise_on_fail :
|
|
158
|
+
If the function fails to obtain the lock, raise an Exception:
|
|
159
|
+
This will be either of type
|
|
160
|
+
TimeoutError if 'timeout_seconds' > 0 and 'wait' is True, or
|
|
161
|
+
BlockingIOError if 'timeout_seconds' == 0 or 'wait' is False.
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
Number of total locks the current process holds, or 0 if the function
|
|
166
|
+
failed to attain a lock.
|
|
167
|
+
"""
|
|
168
|
+
timeout_seconds = int(timeout_seconds) if not timeout_seconds is None else None
|
|
169
|
+
timeout_retry = int(timeout_retry) if not timeout_retry is None else None
|
|
170
|
+
assert not self._filename is None, ("self._filename is None. That probably means 'self' was deleted.")
|
|
171
|
+
|
|
172
|
+
if timeout_seconds is None:
|
|
173
|
+
timeout_seconds = 0 if not wait else 1
|
|
174
|
+
else:
|
|
175
|
+
_log.verify( timeout_seconds>=0, "'timeout_seconds' cannot be negative")
|
|
176
|
+
_log.verify( not wait or timeout_seconds>0, "Using 'timeout_seconds==0' and 'wait=True' is inconsistent.")
|
|
177
|
+
|
|
178
|
+
if not self._fd is None:
|
|
179
|
+
self._cnt += 1
|
|
180
|
+
self.verbose.write("%s: acquire(): raised lock counter to %ld", self._lid, self._cnt)
|
|
181
|
+
return self._cnt
|
|
182
|
+
assert self._cnt == 0
|
|
183
|
+
self._cnt = 0
|
|
184
|
+
|
|
185
|
+
i = 0
|
|
186
|
+
while True:
|
|
187
|
+
self.verbose.write("\r%s: acquire(): locking [%s]... ", self._lid, "windows" if IS_WINDOWS else "linux", end='')
|
|
188
|
+
if not IS_WINDOWS:
|
|
189
|
+
# Linux
|
|
190
|
+
# -----
|
|
191
|
+
try:
|
|
192
|
+
self._fd = os.open(self._filename, os.O_CREAT|os.O_EXCL|os.O_RDWR)
|
|
193
|
+
os.write(self._fd, bytes("%d" % self._pid, 'utf-8'))
|
|
194
|
+
except OSError as e:
|
|
195
|
+
if not self._fd is None:
|
|
196
|
+
os.close(self._fd)
|
|
197
|
+
self._fd = None
|
|
198
|
+
if e.errno != 17:
|
|
199
|
+
self.verbose.write("failed: %s", str(e), head=False)
|
|
200
|
+
raise e
|
|
201
|
+
else:
|
|
202
|
+
# Windows
|
|
203
|
+
# ------
|
|
204
|
+
secur_att = win32security.SECURITY_ATTRIBUTES()
|
|
205
|
+
secur_att.Initialize()
|
|
206
|
+
try:
|
|
207
|
+
self._fd = win32file.CreateFile( self._filename,
|
|
208
|
+
win32con.GENERIC_READ|win32con.GENERIC_WRITE,
|
|
209
|
+
win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE,
|
|
210
|
+
secur_att,
|
|
211
|
+
win32con.OPEN_ALWAYS,
|
|
212
|
+
win32con.FILE_ATTRIBUTE_NORMAL , 0 )
|
|
213
|
+
|
|
214
|
+
ov=pywintypes.OVERLAPPED() #used to indicate starting region to lock
|
|
215
|
+
win32file.LockFileEx(self._fd,win32con.LOCKFILE_EXCLUSIVE_LOCK|win32con.LOCKFILE_FAIL_IMMEDIATELY,0,WIN_HIGHBITS,ov)
|
|
216
|
+
except BaseException as e:
|
|
217
|
+
if not self._fd is None:
|
|
218
|
+
self._fd.Close()
|
|
219
|
+
self._fd = None
|
|
220
|
+
if e.winerror not in [17,33]:
|
|
221
|
+
self.verbose.write("failed: %s", str(e), head=False)
|
|
222
|
+
raise e
|
|
223
|
+
|
|
224
|
+
if not self._fd is None:
|
|
225
|
+
# success
|
|
226
|
+
self._cnt = 1
|
|
227
|
+
self.verbose.write("done; lock counter set to 1", head=False)
|
|
228
|
+
return self._cnt
|
|
229
|
+
|
|
230
|
+
if timeout_seconds <= 0:
|
|
231
|
+
break
|
|
232
|
+
|
|
233
|
+
if not timeout_retry is None:
|
|
234
|
+
i += 1
|
|
235
|
+
if i>timeout_retry:
|
|
236
|
+
break
|
|
237
|
+
self.verbose.write("locked; waiting %s retry %ld/%ld", fmt_seconds(timeout_seconds), i+1, timeout_retry, head=False)
|
|
238
|
+
else:
|
|
239
|
+
self.verbose.write("locked; waiting %s", fmt_seconds(timeout_seconds), head=False)
|
|
240
|
+
|
|
241
|
+
time.sleep(timeout_seconds)
|
|
242
|
+
|
|
243
|
+
if timeout_seconds == 0:
|
|
244
|
+
self.verbose.write("failed.", head=False)
|
|
245
|
+
if raise_on_fail: raise BlockingIOError(self._filename)
|
|
246
|
+
else:
|
|
247
|
+
self.verbose.write("timed out. Cannot access lock.", head=False)
|
|
248
|
+
if raise_on_fail: raise TimeoutError(self._filename, dict(timeout_retry=timeout_retry, timeout_seconds=timeout_seconds))
|
|
249
|
+
return 0
|
|
250
|
+
|
|
251
|
+
def release(self, *, force : bool = False ):
|
|
252
|
+
"""
|
|
253
|
+
Release lock
|
|
254
|
+
By default will only release the lock once the number of acquisitions is zero.
|
|
255
|
+
Use 'force' to always unlock.
|
|
256
|
+
|
|
257
|
+
Parameters
|
|
258
|
+
----------
|
|
259
|
+
force :
|
|
260
|
+
Whether to close the file regardless of its internal counter.
|
|
261
|
+
|
|
262
|
+
Returns
|
|
263
|
+
-------
|
|
264
|
+
Returns numbner of remaining lock counters; in other words returns 0 if the lock is no longer locked by this process.
|
|
265
|
+
"""
|
|
266
|
+
if self._fd is None:
|
|
267
|
+
assert force, ("File was not locked by this process. Use 'force' to avoid this message if need be.")
|
|
268
|
+
self._cnt = 0
|
|
269
|
+
return 0
|
|
270
|
+
assert self._cnt > 0
|
|
271
|
+
self._cnt -= 1
|
|
272
|
+
if self._cnt > 0 and not force:
|
|
273
|
+
self.verbose.write("%s: release(): lock counter lowered to %ld", self._lid, self._cnt)
|
|
274
|
+
return self._cnt
|
|
275
|
+
|
|
276
|
+
self.verbose.write("%s: release(): unlocking [%s]... ", self._lid, "windows" if IS_WINDOWS else "linux", end='')
|
|
277
|
+
err = ""
|
|
278
|
+
if not IS_WINDOWS:
|
|
279
|
+
# Linux
|
|
280
|
+
# Locks on Linxu are remarably shaky.
|
|
281
|
+
# In particular, it is possible to remove a locked file.
|
|
282
|
+
try:
|
|
283
|
+
os.remove(self._filename)
|
|
284
|
+
except:
|
|
285
|
+
pass
|
|
286
|
+
try:
|
|
287
|
+
os.close(self._fd)
|
|
288
|
+
except:
|
|
289
|
+
err = "*** WARNING: could not close file."
|
|
290
|
+
pass
|
|
291
|
+
else:
|
|
292
|
+
try:
|
|
293
|
+
ov=pywintypes.OVERLAPPED() #used to indicate starting region to lock
|
|
294
|
+
win32file.UnlockFileEx(self._fd,0,WIN_HIGHBITS,ov)
|
|
295
|
+
except:
|
|
296
|
+
err = "*** WARNING: could not unlock file."
|
|
297
|
+
pass
|
|
298
|
+
try:
|
|
299
|
+
self._fd.Close()
|
|
300
|
+
except:
|
|
301
|
+
err = "*** WARNING: could not close file."
|
|
302
|
+
pass
|
|
303
|
+
try:
|
|
304
|
+
win32file.DeleteFile(self._filename)
|
|
305
|
+
except:
|
|
306
|
+
err = "*** WARNING: could not delete file." if err == "" else err
|
|
307
|
+
pass
|
|
308
|
+
self.verbose.write("file deleted." if err=="" else err, head=False)
|
|
309
|
+
self._fd = None
|
|
310
|
+
self._cnt = 0
|
|
311
|
+
return 0
|
|
312
|
+
|
|
313
|
+
# context manager
|
|
314
|
+
# ---------------
|
|
315
|
+
|
|
316
|
+
def __enter__(self):
|
|
317
|
+
""" Simply returns 'self' """
|
|
318
|
+
return self
|
|
319
|
+
|
|
320
|
+
def __exit__(self, *kargs, **kwargs):
|
|
321
|
+
""" Force-release the lock """
|
|
322
|
+
self.release( force=True )
|
|
323
|
+
return False # raise exceptions
|
|
324
|
+
|
|
325
|
+
def AttemptLock(filename, * ,
|
|
326
|
+
release_on_exit : bool = True,
|
|
327
|
+
wait : bool = True,
|
|
328
|
+
timeout_seconds : int = None,
|
|
329
|
+
timeout_retry : int = None,
|
|
330
|
+
verbose : Context = Context.quiet ) -> FileLock:
|
|
331
|
+
"""
|
|
332
|
+
Attempt to acquire a new lock with name 'filename', and return None upon failure.
|
|
333
|
+
Note that in contrast to FileLock() 'raise_on_fail' defaults to False for this function call.
|
|
334
|
+
|
|
335
|
+
Parameters
|
|
336
|
+
----------
|
|
337
|
+
filename :
|
|
338
|
+
Filename of the lock.
|
|
339
|
+
'filename' may start with '!/' to refer to the temp directory, or '~/' to refer to the user directory.
|
|
340
|
+
On Unix /dev/shm/ can be used to refer to shared memory.
|
|
341
|
+
release_on_exit :
|
|
342
|
+
Whether to auto-release the lock upon exit.
|
|
343
|
+
wait :
|
|
344
|
+
If False, return immediately if the lock cannot be acquired.
|
|
345
|
+
If True, wait with below parameters; in particular if these are left as defaults the lock will wait indefinitely.
|
|
346
|
+
timeout_seconds :
|
|
347
|
+
Number of seconds to wait before retrying.
|
|
348
|
+
Set to 0 to fail immediately.
|
|
349
|
+
If set to None, then its value will depend on 'wait'.
|
|
350
|
+
If wait is True, then timeout_seconds==1; if wait is False, then timeout_seconds==0
|
|
351
|
+
timeout_retry :
|
|
352
|
+
How many times to retry before timing out.
|
|
353
|
+
Set to None to retry indefinitely.
|
|
354
|
+
verbose :
|
|
355
|
+
Context which will print out operating information of the lock. This is helpful for debugging.
|
|
356
|
+
In particular, it will track __del__() function calls.
|
|
357
|
+
Set to None to print all context.
|
|
358
|
+
|
|
359
|
+
Exceptions
|
|
360
|
+
----------
|
|
361
|
+
Will not raise any exceptions
|
|
362
|
+
|
|
363
|
+
Returns
|
|
364
|
+
-------
|
|
365
|
+
Filelock if acquired or None
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
lock = FileLock( filename=filename,
|
|
369
|
+
acquire=True,
|
|
370
|
+
release_on_exit=release_on_exit,
|
|
371
|
+
wait=wait,
|
|
372
|
+
timeout_seconds=timeout_seconds,
|
|
373
|
+
timeout_retry=timeout_retry,
|
|
374
|
+
raise_on_fail=False,
|
|
375
|
+
verbose=verbose )
|
|
376
|
+
return lock if lock.locked else None
|
|
377
|
+
|
|
378
|
+
def AcquireLock(filename, * ,
|
|
379
|
+
wait : bool = True,
|
|
380
|
+
timeout_seconds : int = None,
|
|
381
|
+
timeout_retry : int = None,
|
|
382
|
+
verbose : Context = Context.quiet ) -> FileLock:
|
|
383
|
+
"""
|
|
384
|
+
Aquires a filelock indentified by `filename`. Raises an exception of this was not successful.
|
|
385
|
+
This function is a short cut for FileLock(..., acquire=True ) to be used in context blocks:
|
|
386
|
+
|
|
387
|
+
with AcquireLock( "!/my.lock" ):
|
|
388
|
+
...
|
|
389
|
+
....
|
|
390
|
+
|
|
391
|
+
Parameters
|
|
392
|
+
----------
|
|
393
|
+
filename :
|
|
394
|
+
Filename of the lock.
|
|
395
|
+
'filename' may start with '!/' to refer to the temp directory, or '~/' to refer to the user directory.
|
|
396
|
+
On Unix /dev/shm/ can be used to refer to shared memory.
|
|
397
|
+
wait :
|
|
398
|
+
If False, return immediately if the lock cannot be acquired.
|
|
399
|
+
If True, wait with below parameters; in particular if these are left as defaults the lock will wait indefinitely.
|
|
400
|
+
timeout_seconds :
|
|
401
|
+
Number of seconds to wait before retrying.
|
|
402
|
+
Set to 0 to fail immediately.
|
|
403
|
+
If set to None, then its value will depend on 'wait'.
|
|
404
|
+
If wait is True, then timeout_seconds==1; if wait is False, then timeout_seconds==0
|
|
405
|
+
timeout_retry :
|
|
406
|
+
How many times to retry before timing out.
|
|
407
|
+
Set to None to retry indefinitely.
|
|
408
|
+
verbose :
|
|
409
|
+
Context which will print out operating information of the lock. This is helpful for debugging.
|
|
410
|
+
In particular, it will track __del__() function calls.
|
|
411
|
+
Set to None to print all context.
|
|
412
|
+
|
|
413
|
+
Exceptions
|
|
414
|
+
----------
|
|
415
|
+
Will raise an exception if timeout is not indefinitely and the lock could not be acquired.
|
|
416
|
+
|
|
417
|
+
Returns
|
|
418
|
+
-------
|
|
419
|
+
Filelock if acquired or None
|
|
420
|
+
"""
|
|
421
|
+
|
|
422
|
+
return FileLock( filename=filename,
|
|
423
|
+
acquire=True,
|
|
424
|
+
release_on_exit=True,
|
|
425
|
+
wait=wait,
|
|
426
|
+
timeout_seconds=timeout_seconds,
|
|
427
|
+
timeout_retry=timeout_retry,
|
|
428
|
+
raise_on_fail=True,
|
|
429
|
+
verbose=verbose )
|
|
430
|
+
|