#!/usr/bin/env python
# -*- coding: utf-8 -*
# Copyright: [CUP] - See LICENSE for details.
# Authors: Guannan Ma (@mythmgn),
"""
:description:
file related functions
"""
import os
import sys
import fcntl
from cup import err
from cup import decorators
from cup import platforms
if platforms.is_linux():
import tempfile
__all__ = [
'LockFile', 'FILELOCK_SHARED', 'FILELOCK_EXCLUSIVE',
'FILELOCK_NONBLOCKING', 'FILELOCK_UNLOCK', 'TempFile'
]
FILELOCK_EXCLUSIVE = fcntl.LOCK_EX
FILELOCK_SHARED = fcntl.LOCK_SH
FILELOCK_NONBLOCKING = fcntl.LOCK_NB
FILELOCK_UNLOCK = fcntl.LOCK_UN
[docs]class LockFile(object):
"""
lock file class
"""
def __init__(self, fpath, locktype=FILELOCK_EXCLUSIVE):
"""
exclusive lockfile, by default.
Notice that the file CANNOT exist before you intialize a LockFile obj.
Otherwise, it will raise cup.err.LockFileError
:raise:
cup.err.LockFileError if we encounter errors
"""
self._fpath = fpath
self._locktype = locktype
self._fhandle = None
try:
# if FILELOCK_EXCLUSIVE == locktype:
# self._fhandle = os.open(
# self._fpath, os.O_CREAT|os.O_EXCL|os.O_RDWR
# )
# else:
self._fhandle = os.open(
self._fpath, os.O_CREAT | os.O_RDWR
)
except IOError as error:
raise err.LockFileError(error)
except OSError as error:
raise err.LockFileError(error)
except Exception as error:
raise err.LockFileError(
'catch unkown error type:{0}'.format(error)
)
def __del__(self):
"""del the instance"""
try:
if self._fhandle is not None:
os.close(self._fhandle)
# pylint: disable=W0703
except Exception as error:
sys.stderr.write('failed to close lockfile:{0}, msg:{1}'.format(
self._fpath, error)
)
sys.stderr.flush()
[docs] @decorators.needposix
def lock(self, blocking=True):
"""
lock the file
:param blocking:
If blocking is True, will block there until cup gets the lock.
True by default.
:return:
return False if locking fails
:raise Exception:
raise cup.err.LockFileError if blocking is False and
the lock action failed
"""
flags = 0x1
if FILELOCK_SHARED == self._locktype:
flags = FILELOCK_SHARED
elif FILELOCK_EXCLUSIVE == self._locktype:
flags = FILELOCK_EXCLUSIVE
else:
raise err.LockFileError('does not support this lock type')
if not blocking:
flags |= FILELOCK_NONBLOCKING
ret = None
try:
ret = fcntl.flock(self._fhandle, flags)
except IOError as error:
raise err.LockFileError(error)
except Exception as error:
raise err.LockFileError(error)
return ret
[docs] def unlock(self):
"""unlock the locked file"""
try:
fcntl.flock(self._fhandle, FILELOCK_UNLOCK)
except Exception as error:
raise err.LockFileError(error)
[docs]class TempFile(object):
"""
tempfile, the temp file will be deleted immediately after the lifetime.
You can use TempFile like the original Python File Object.
::
tmp = TempFile('./')
tmp.write / read /seek / etc
tmp.close()
"""
def __init__(self, filedir, prefix='', suffix=''):
"""
:param filedir:
temp file dir which contains the temp file
:prefix:
prefix of the temp filename
:suffix:
suffix of the file name. e.g. '.tmp'.
"""
self._fdir = filedir
self._fp = None
self._prefix = prefix
self._suffix = suffix
def __enter__(self):
"""enter"""
if platforms.is_linux():
self._fp = tempfile.TemporaryFile(
dir=self._fdir,
prefix=self._prefix,
suffix=self._suffix
)
return self._fp
else:
raise err.NotImplementedYet('TemporaryFile')
def __exit__(self, exc_type, exc_val, exc_tb):
"""
exit
"""
if platforms.is_linux():
self._fp.close()
# vi:set tw=0 ts=4 sw=4 nowrap fdm=indent