Module utils¶
Utilities.
New in version 0.5.0.
Overview¶
Raised by |
|
Simple stop watch. |
|
Raised by |
|
Check if an object is a bytes-like object. |
|
Check if an object is a path-like object. |
|
Check the type of an object. |
|
Helper function for docopt. |
|
Make sure that only one instance of the program/script is running. |
|
Exit from Python. |
-
exception
salmagundi.utils.
AlreadyRunning
[source]¶ Raised by
ensure_single_instance()
.
-
class
salmagundi.utils.
StopWatch
(start=True)[source]¶ Simple stop watch.
- Parameters
start (bool) – if
True
the stop watch starts immediately
New in version 0.12.0.
-
property
started
¶ Return whether the stop watch has been started.
-
property
running
¶ Return whether the stop watch is running.
-
start
()[source]¶ Start or restart the stop watch.
- Raises
StopWatchError – if the stop watch is running
-
pause
()[source]¶ Pause the stop watch.
Does not reset the stop watch.
- Returns
the elapsed time in seconds
- Return type
- Raises
StopWatchError – if the stop watch is not running
-
stop
()[source]¶ Stop and reset the stop watch.
- Returns
the elapsed time in seconds
- Return type
- Raises
StopWatchError – if the stop watch is not running
-
reset
()[source]¶ Reset the stop watch.
- Raises
StopWatchError – if the stop watch is running
-
time
()[source]¶ Get elapsed time from the stop watch.
- Returns
the currently elapsed time in seconds
- Return type
- Raises
StopWatchError – if the stop watch has not been started
-
exception
salmagundi.utils.
StopWatchError
[source]¶ Raised by
StopWatch
if an action is not allowed.New in version 0.12.0.
-
salmagundi.utils.
check_bytes_like
(obj, name='object', msg=None)[source]¶ Check if an object is a bytes-like object.
-
salmagundi.utils.
check_path_like
(obj, name='object', msg=None)[source]¶ Check if an object is a path-like object.
-
salmagundi.utils.
check_type
(obj, classinfo, name='object', msg=None)[source]¶ Check the type of an object.
>>> utils.check_type(1, str, 'num') Traceback (most recent call last): ... TypeError: the type of 'num' must be 'str', got 'int' >>> utils.check_type(1, (str, float), 'num') Traceback (most recent call last): ... TypeError: the type of 'num' must be one of 'str, float', got 'int' >>> utils.check_type(1, str, msg='wrong type for num') Traceback (most recent call last): ... TypeError: wrong type for num
- Parameters
obj (object) – the object
classinfo – see
isinstance()
name (str) – name shown in the exception message
msg (str) – message for the exception
- Raises
TypeError – if the check fails
-
salmagundi.utils.
docopt_helper
(text, *, name=None, version=None, version_str=None, argv=None, help=True, options_first=False, converters=None, err_code=1, **kwargs)[source]¶ Helper function for docopt.
The
name
defaults toos.path.basename(sys.argv[0])
.If
version
is atuple
it will be converted to a string with'.'.join(map(str, version))
.If
version_str
is set it will be printed if called with--version
. Else ifversion
is set the resulting string will bename + ' ' + version
.Within the help message string substitution is supported with template strings. The placeholder identifiers
name
,version
andversion_str
are always available; more can be added withkwargs
.If the help message is indented it will be dedented so that the least indented lines line up with the left edge of the display.
The optional argument
converters
is a mapping with the same keys as in the dictionary returned by docopt.docopt(). The values are callables which take one argument of an appropriate type and return a value of the desired type. It is not required to provide a converter for every option, argument and command. If a value cannot be converted the converter should raise aValueError
.Example (naval_fate.py):
#!/usr/bin/env python3 """$title Version $version. Usage: $name ship new <name>... $name ship <name> move <x> <y> [--speed=<kn>] $name ship shoot <x> <y> $name mine (set|remove) <x> <y> [--moored | --drifting] $name (-h | --help) $name --version Options: -h --help Show this screen. --version Show version. --speed=<kn> Speed in knots [default: $speed]. --moored Moored (anchored) mine. --drifting Drifting mine. """ import os from salmagundi.utils import docopt_helper __version__ = '2.0' if __name__ == '__main__': def int_conv(x): if x is not None: x = int(x) if x < 0: raise ValueError('value < 0') return x arguments = docopt_helper( __doc__, version=__version__, converters={ '<x>': int_conv, '<y>': int_conv, '--speed': int_conv, }, title='Naval Fate', speed=os.environ.get('NAVAL_FATE_SPEED', '10')) print(arguments)
$ ./naval_fate.py -h Naval Fate Version 2.0. Usage: naval_fate.py ship new <name>... naval_fate.py ship <name> move <x> <y> [--speed=<kn>] naval_fate.py ship shoot <x> <y> naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed=<kn> Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. $ ./naval_fate.py --version naval_fate.py 2.0 $ ./naval_fate.py ship Titanic move 42 84 {'--drifting': False, '--help': False, '--moored': False, '--speed': 10, '--version': False, '<name>': ['Titanic'], '<x>': 42, '<y>': 84, 'mine': False, 'move': True, 'new': False, 'remove': False, 'set': False, 'ship': True, 'shoot': False} $ ./naval_fate.py ship Titanic move 42 84 --speed=-10 error in '--speed': value < 0 $ ./naval_fate.py ship Titanic move 42 84 --speed=abc error in '--speed': invalid literal for int() with base 10: 'abc'
- Parameters
text (str) – help message
name (str) – name of program/script
version_str (str) – version string
argv (list(str)) – see: docopt.docopt()
option_first (bool) – see: docopt.docopt()
help (bool) – see: docopt.docopt()
err_code (int) – exit status code if an error occurs
kwargs – additional values for substitution in the help message
- Returns
result of docopt.docopt()
- Return type
- Raises
SystemExit – if program was invoked with incorrect arguments or a converter function raised a
ValueError
New in version 0.10.0.
Changed in version 0.11.0: Add parameter
err_code
-
salmagundi.utils.
ensure_single_instance
(lockname=None, *, lockdir=None, extra=None, err_code=1, err_msg=None, use_socket=False)[source]¶ Make sure that only one instance of the program/script is running.
The result of this function can be used as a context manager in with statements or as a decorator.
def main(): ... if __name__ == '__main__': with ensure_single_instance(): main() # is equivalent to: @ensure_single_instance() def main(): ... if __name__ == '__main__': main()
If
lockname
is not set the name will be constructed from the absolute path of the program/script and the lock file will be created in thelockdir
(which defaults to the temporary directory).On Linux ,if
use_socket=True
, an abstract domain socket will be used instead of a lock file and the name of the socket will be the value oflockname
.This function should work on Windows and any platform that supports
fcntl
but it is only tested on Linux. The user running the program/script must have the permissions to create and delete the lock file. If the program/script will be run by multiple users the single instance restriction can be per user or system wide. The temporary directory on Windows is normally user specific; on unix-like systems it is normally one directory for all users. To create a user specific lock name theextra
argument can be used:import getpass from salmagundi.utils import ensure_single_instance with ensure_single_instance(extra=getpass.getuser()): ...
- Parameters
lockname (str) – user defined lock name
lockdir (path-like object) – user defined directory for lock files (must exist and the path must be absolute; ignored if
use_socket=True
)extra (str) – will be appended to lock name
err_code (int or None) – exit status code if another instance is running (if set to
None
AlreadyRunning
will be raised instead ofSystemExit
)err_msg (str or None) – error message (if
None
it defaults tof'already running: {sys.argv[0]}'
)use_socket (bool) – if true an abstract domain socket is used (Linux only)
- Raises
SystemExit – if another instance is running and
err_code
is not NoneAlreadyRunning – if another instance is running and
err_code
is NoneRuntimeError – if
lockdir
is not absolute oruse_socket=True
and platform is not LinuxOSError – if the lock file could not be created/deleted
New in version 0.11.0.
Changed in version 0.11.2: Rename parameter
lockfile
tolockname
-
salmagundi.utils.
sys_exit
(arg=None, code=None, *, logger=None)[source]¶ Exit from Python.
If
code
is not an integer, this function callssys.exit()
witharg
as its argument. Otherwisearg
will be printed tosys.stderr
if it is notNone
andsys.exit()
will be called withcode
as its argument.If
logger
is set, the message, if any, will be logged with levelCRITICAL
instead of printing it tosys.stderr
.- Parameters
arg – see:
sys.exit()
logger (logging.Logger) – a logger
- Raises
New in version 0.11.0.