Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
csppfetch
Manage
Activity
Members
Labels
Plan
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
cspp_geo
csppfetch
Commits
cf57a3a7
Commit
cf57a3a7
authored
4 years ago
by
Alan De Smet
Browse files
Options
Downloads
Patches
Plain Diff
Cleaning up exclusivelockfile
parent
57c22b34
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
csppfetch/exclusivelockfile.py
+52
-124
52 additions, 124 deletions
csppfetch/exclusivelockfile.py
with
52 additions
and
124 deletions
csppfetch/exclusivelockfile.py
+
52
−
124
View file @
cf57a3a7
...
...
@@ -6,20 +6,56 @@ import logging
class
ExclusiveLockFile
:
"""
Lock a file by name or handle, returning an open file handle
Intended to
be used in a
"
with
"
block as a context manager.
Can
be used in a
"
with
"
block as a context manager.
>>>
import
tempfile
>>>
with
tempfile
.
TemporaryDirectory
()
as
dir
:
...
lockfile
=
dir
+
"
/lock
"
...
open
(
lockfile
,
"
w
"
).
close
()
...
with
ExclusiveLockFile
(
lockfile
)
as
f
:
...
# Can assume exclusive control of lockfile
...
# Can use f as a file object
...
pass
...
f
=
open
(
lockfile
,
"
w
"
)
...
with
ExclusiveLockFile
(
f
):
...
# Can assume exclusive control of lockfile
...
pass
>>>
from
exclusivelockfile
import
ExclusiveLockFile
>>>
from
tempfile
import
mkdtemp
>>>
tmpdir
=
mkdtemp
()
>>>
filename
=
tmpdir
+
"
/lock
"
>>>
>>>
# You can't lock a file until it exists
>>>
>>>
ExclusiveLockFile
(
filename
)
# doctest: +ELLIPSIS
Traceback
(
most
recent
call
last
):
...
FileNotFoundError
:
[
Errno
2
]
No
such
file
or
directory
:
'
.../lock
'
>>>
>>>
# You can lock a file-like object that support f.name and fcntl.lockf(f)
>>>
>>>
f
=
open
(
filename
,
"
w
"
)
>>>
with
ExclusiveLockFile
(
f
):
...
# Can assume exclusive control of filename
...
pass
>>>
f
.
close
()
>>>
>>>
# You can lock an existing file by name (str, bytes, or Path-like object).
>>>
>>>
with
ExclusiveLockFile
(
filename
)
as
f
:
...
# Can assume exclusive control of filename
...
# Can use f as a file object
...
pass
>>>
>>>
# Also supports manual use; you MUST call unlock in this case!
>>>
>>>
l
=
ExclusiveLockFile
(
filename
)
>>>
l
.
lock
()
>>>
# Can assume exclusive control of filename
>>>
l
.
unlock
()
>>>
>>>
# Error cases
>>>
l
.
unlock
()
# doctest: +ELLIPSIS
Traceback
(
most
recent
call
last
):
...
RuntimeError
:
Attempting
to
unlock
...
/
lock
,
but
I
don
'
t have that lock
>>>
l
.
lock
()
>>>
l
.
lock
()
# doctest: +ELLIPSIS
Traceback
(
most
recent
call
last
):
...
RuntimeError
:
Attempting
to
lock
...
/
lock
,
but
I
already
have
that
lock
>>>
>>>
import
os
>>>
os
.
unlink
(
filename
)
>>>
os
.
rmdir
(
tmpdir
)
"""
def __init__(self, filename_or_file):
...
...
@@ -31,56 +67,7 @@ class ExclusiveLockFile:
file-like objects will only work to the extent that
fcntl.lockf works on them.
>>>
from
exclusivelockfile
import
ExclusiveLockFile
>>>
from
tempfile
import
mkdtemp
>>>
tmpdir
=
mkdtemp
()
>>>
filename
=
tmpdir
+
"
/lock
"
>>>
>>>
# You can't lock a file until it exists
>>>
>>>
ExclusiveLockFile
(
filename
)
# doctest: +ELLIPSIS
Traceback
(
most
recent
call
last
):
...
FileNotFoundError
:
[
Errno
2
]
No
such
file
or
directory
:
'
.../lock
'
>>>
>>>
# You can lock a file-like object that support f.name and fcntl.lockf(f)
>>>
>>>
f
=
open
(
filename
,
"
w
"
)
>>>
with
ExclusiveLockFile
(
f
):
...
# Can assume exclusive control of filename
...
pass
>>>
f
.
close
()
>>>
>>>
# You can lock an existing file by name (str, bytes, or Path-like object).
>>>
>>>
with
ExclusiveLockFile
(
filename
)
as
f
:
...
# Can assume exclusive control of filename
...
# Can use f as a file object
...
pass
>>>
>>>
# Also supports manual use; you MUST call unlock in this case!
>>>
>>>
l
=
ExclusiveLockFile
(
filename
)
>>>
l
.
lock
()
>>>
# Can assume exclusive control of filename
>>>
l
.
unlock
()
>>>
>>>
# Error cases
>>>
l
.
unlock
()
# doctest: +ELLIPSIS
Traceback
(
most
recent
call
last
):
...
RuntimeError
:
Attempting
to
unlock
...
/
lock
,
but
I
don
'
t have that lock
>>>
l
.
lock
()
>>>
l
.
lock
()
# doctest: +ELLIPSIS
Traceback
(
most
recent
call
last
):
...
RuntimeError
:
Attempting
to
lock
...
/
lock
,
but
I
already
have
that
lock
>>>
>>>
import
os
>>>
os
.
unlink
(
filename
)
>>>
os
.
rmdir
(
tmpdir
)
Extended examples are in help(exclusivelockfile.ExclusiveLockFile)
"""
try:
# Ensure it
'
s
Path
-
like
...
...
@@ -88,7 +75,7 @@ class ExclusiveLockFile:
self
.
file
=
None
self
.
filename
=
filename_or_file
except
:
#
Hopefully
it's file-like
#
Not Path-like? I hope
it's file-like
self
.
file
=
filename_or_file
self
.
filename
=
None
...
...
@@ -202,7 +189,7 @@ def file_matches_filename(file, filename):
return
False
class
AtomicCreateIfMissing
:
"""
Context
manager
to
atomically
crate
a
file
"""
Context manager to atomically cr
e
ate a file
>>>
from
exclusivelockfile
import
AtomicCreateIfMissing
>>>
from
tempfile
import
mkdtemp
...
...
@@ -264,62 +251,3 @@ class AtomicCreateIfMissing:
os
.
rename
(
self
.
lockfilename
,
self
.
filename
)
self
.
lock
.
unlock
()
if False:
class ExclusiveLockFileOLD:
"""
Lock
a
temporary
file
created
for
the
purpose
.
Intended
to
be
used
in
a
"
with
"
block
as
a
context
manager
.
The
file
will
be
created
if
it
doesn
'
t exist. It will be deleted when the
block exits! The filename should not be a directory.
If multiple processes try to lock the same file, the first to succeed will
delete it when done. That means that a process starting after that point
will create _new_ file and lock that, not sharing the previous one! This
makes it only suitable for VERY specialized purposes (like ensuring only
one process downloads a file, and later processes will immediately bail out
if the downloaded file is already preent).
Be warned that this is implemented using fcntl.lockf which is an ADVISORY
lock; only code using fcntl.lockf or similar will resepect it.
WILL create missing directories if necessary, will NOT
remove them on completion.
>>>
import
tempfile
>>>
with
tempfile
.
TemporaryDirectory
()
as
dir
:
...
with
ExclusiveLockFile
(
dir
+
"
/lock
"
):
...
# In this block, the file f.name is exclusively locked
...
# using fcntl.lockf. (Only code using fcntl.lockf or
...
# equivalent will respect this!)
...
pass
"""
def
__init__
(
self
,
filename
):
self
.
filename
=
filename
def
lock
(
self
):
dir
=
os
.
path
.
dirname
(
self
.
filename
)
if
len
(
dir
)
and
not
os
.
path
.
exists
(
dir
):
logging
.
debug
(
"
directory {} does not exist to hold lockfile {}; creating
"
.
format
(
dir
,
self
.
filename
))
os
.
makedirs
(
dir
)
logging
.
debug
(
"
Attempting to lock {0}
"
.
format
(
self
.
filename
))
self
.
f
=
open
(
self
.
filename
,
"
w
"
)
fcntl
.
lockf
(
self
.
f
,
fcntl
.
LOCK_EX
)
logging
.
debug
(
"
Locked {0}
"
.
format
(
self
.
filename
))
def
unlock
(
self
):
fcntl
.
lockf
(
self
.
f
,
fcntl
.
LOCK_UN
)
self
.
f
.
close
()
try
:
os
.
unlink
(
self
.
filename
)
except
FileNotFoundError
:
# another lock erased me; we're okay with that
pass
logging
.
debug
(
"
unlocked {0}
"
.
format
(
self
.
filename
))
def
__enter__
(
self
):
self
.
lock
()
def
__exit__
(
self
,
type
,
value
,
traceback
):
self
.
unlock
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment