octoprint.util¶
This module bundles commonly used utility methods or helper classes that are used in multiple places within OctoPrint’s source code.
- class octoprint.util.CaseInsensitiveSet(*args)¶
Basic case insensitive set
Any str values will be stored and compared in lower case. Other value types are left as-is.
-
class octoprint.util.DefaultOrderedDict(default_factory=
None
, *a, **kw)¶ - copy() a shallow copy of od ¶
-
class octoprint.util.RepeatedTimer(interval, function, args=
None
, kwargs=None
, run_first=False
, condition=None
, on_condition_false=None
, on_cancelled=None
, on_finish=None
, daemon=True
)¶ This class represents an action that should be run repeatedly in an interval. It is similar to python’s own
threading.Timer
class, but instead of only running once thefunction
will be run again and again, sleeping the statedinterval
in between.RepeatedTimers are started, as with threads, by calling their
start()
method. The timer can be stopped (in between runs) by calling thecancel()
method. The interval the time waited before execution of a loop may not be exactly the same as the interval specified by the user.For example:
def hello(): print("Hello World!") t = RepeatedTimer(1.0, hello) t.start() # prints "Hello World!" every second
Another example with dynamic interval and loop condition:
count = 0 maximum = 5 factor = 1 def interval(): global count global factor return count * factor def condition(): global count global maximum return count <= maximum def hello(): print("Hello World!") global count count += 1 t = RepeatedTimer(interval, hello, run_first=True, condition=condition) t.start() # prints "Hello World!" 5 times, printing the first one # directly, then waiting 1, 2, 3, 4s in between (adaptive interval)
- Parameters:¶
- interval : float or callable¶
The interval between each
function
call, in seconds. Can also be a callable returning the interval to use, in case the interval is not static.- function : callable¶
The function to call.
- args : list or tuple¶
The arguments for the
function
call. Defaults to an empty list.- kwargs : dict¶
The keyword arguments for the
function
call. Defaults to an empty dict.- run_first : boolean¶
If set to True, the function will be run for the first time before the first wait period. If set to False (the default), the function will be run for the first time after the first wait period.
- condition : callable¶
Condition that needs to be True for loop to continue. Defaults to
lambda: True
.- on_condition_false : callable¶
Callback to call when the timer finishes due to condition becoming false. Will be called before the
on_finish
callback.- on_cancelled : callable¶
Callback to call when the timer finishes due to being cancelled. Will be called before the
on_finish
callback.- on_finish : callable¶
Callback to call when the timer finishes, either due to being cancelled or since the condition became false.
- daemon : bool¶
daemon flag to set on underlying thread.
- run()¶
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.
-
class octoprint.util.ResettableTimer(interval, function, args=
None
, kwargs=None
, on_reset=None
, on_cancelled=None
, daemon=True
)¶ This class represents an action that should be run after a specified amount of time. It is similar to python’s own
threading.Timer
class, with the addition of being able to reset the counter to zero.ResettableTimers are started, as with threads, by calling their
start()
method. The timer can be stopped (in between runs) by calling thecancel()
method. Resetting the counter can be done with thereset()
method.For example:
def hello(): print("Ran hello() at {}").format(time.time()) t = ResettableTimer(60.0, hello) t.start() print("Started at {}").format(time.time()) time.sleep(30) t.reset() print("Reset at {}").format(time.time())
- Parameters:¶
- interval : float or callable¶
The interval before calling
function
, in seconds. Can also be a callable returning the interval to use, in case the interval is not static.- function : callable¶
The function to call.
- args : list or tuple¶
The arguments for the
function
call. Defaults to an empty list.- kwargs : dict¶
The keyword arguments for the
function
call. Defaults to an empty dict.- on_cancelled : callable¶
Callback to call when the timer finishes due to being cancelled.
- on_reset : callable¶
Callback to call when the timer is reset.
- daemon : bool¶
daemon flag to set on underlying thread.
- run()¶
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.
-
class octoprint.util.TypedQueue(maxsize=
0
)¶ - get(*args, **kwargs)¶
Remove and return an item from the queue.
If optional args ‘block’ is true and ‘timeout’ is None (the default), block if necessary until an item is available. If ‘timeout’ is a non-negative number, it blocks at most ‘timeout’ seconds and raises the Empty exception if no item was available within that time. Otherwise (‘block’ is false), return an item if one is immediately available, else raise the Empty exception (‘timeout’ is ignored in that case).
-
put(item, item_type=
None
, *args, **kwargs)¶ Put an item into the queue.
If optional args ‘block’ is true and ‘timeout’ is None (the default), block if necessary until a free slot is available. If ‘timeout’ is a non-negative number, it blocks at most ‘timeout’ seconds and raises the Full exception if no free slot was available within that time. Otherwise (‘block’ is false), put an item on the queue if a free slot is immediately available, else raise the Full exception (‘timeout’ is ignored in that case).
- octoprint.util.chunks(l, n)¶
Yield successive n-sized chunks from l.
Taken from http://stackoverflow.com/a/312464/2028598
-
octoprint.util.deprecated(message, stacklevel=
1
, since=None
, includedoc=None
, extenddoc=False
)¶ A decorator for deprecated methods. Logs a deprecation warning via Python’s :mod:`warnings module including the supplied
message
. The call stack level used (for adding the source location of the offending call to the warning) can be overridden using the optionalstacklevel
parameter. If bothsince
andincludedoc
are provided, a deprecation warning will also be added to the function’s docstring by providing or extending its__doc__
property.- Parameters:¶
- message : string¶
The message to include in the deprecation warning.
- stacklevel : int¶
Stack level for including the caller of the offending method in the logged warning. Defaults to 1, meaning the direct caller of the method. It might make sense to increase this in case of the function call happening dynamically from a fixed position to not shadow the real caller (e.g. in case of overridden
getattr
methods).- includedoc : string¶
Message about the deprecation to include in the wrapped function’s docstring.
- extenddoc : boolean¶
If True the original docstring of the wrapped function will be extended by the deprecation message, if False (default) it will be replaced with the deprecation message.
- since : string¶
Version since when the function was deprecated, must be present for the docstring to get extended.
- Returns:¶
The wrapped function with the deprecation warnings in place.
- Return type:¶
function
-
octoprint.util.deserialize(filename, encoding=
'utf-8'
)¶ Deserializes data from a file
In the current implementation this uses json.loads and - if the file is found to be compressed - zlib.decompress.
- octoprint.util.dict_clean(a, b)¶
Recursively deep-sanitizes
a
based onb
, removing all keys (and associated values) froma
that do not appear inb
.Example:
>>> a = dict(foo="foo", bar="bar", fnord=dict(a=1, b=2, l=["some", "list"])) >>> b = dict(foo=None, fnord=dict(a=None, b=None)) >>> expected = dict(foo="foo", fnord=dict(a=1, b=2)) >>> dict_sanitize(a, b) == expected True >>> dict_clean(a, b) == expected True
- Parameters:¶
- Results:
dict: A new dict based on
a
with all keys (and corresponding values) found inb
removed.
- octoprint.util.dict_contains_all_keys(keys, dictionary)¶
Recursively deep-checks if
dictionary
contains all keys found inkeys
.Example:
>>> positive = dict(foo="some_other_bar", fnord=dict(b=100)) >>> negative = dict(foo="some_other_bar", fnord=dict(b=100, d=20)) >>> dictionary = dict(foo="bar", fnord=dict(a=1, b=2, c=3)) >>> dict_contains_all_keys(positive, dictionary) True >>> dict_contains_all_keys(negative, dictionary) False
- octoprint.util.dict_contains_any_keys(keys, dictionary)¶
Recursively deep-checks if
dictionary
contains any keys found inkeys
.Example:
>>> positive = dict(foo="some_other_bar") >>> negative = dict(fnord=dict(e=True)) >>> dictionary = dict(foo="bar", fnord=dict(a=1, b=2, c=3)) >>> dict_contains_any_keys(positive, dictionary) True >>> dict_contains_any_keys(negative, dictionary) False
- octoprint.util.dict_contains_keys(keys, dictionary)¶
Recursively deep-checks if
dictionary
contains all keys found inkeys
.Example:
>>> positive = dict(foo="some_other_bar", fnord=dict(b=100)) >>> negative = dict(foo="some_other_bar", fnord=dict(b=100, d=20)) >>> dictionary = dict(foo="bar", fnord=dict(a=1, b=2, c=3)) >>> dict_contains_all_keys(positive, dictionary) True >>> dict_contains_all_keys(negative, dictionary) False
- octoprint.util.dict_filter(dictionary, filter_function)¶
Filters a dictionary with the provided filter_function
Example:
>>> data = dict(key1="value1", key2="value2", other_key="other_value", foo="bar", bar="foo") >>> dict_filter(data, lambda k, v: k.startswith("key")) == dict(key1="value1", key2="value2") True >>> dict_filter(data, lambda k, v: v.startswith("value")) == dict(key1="value1", key2="value2") True >>> dict_filter(data, lambda k, v: k == "foo" or v == "foo") == dict(foo="bar", bar="foo") True >>> dict_filter(data, lambda k, v: False) == dict() True >>> dict_filter(data, lambda k, v: True) == data True >>> dict_filter(None, lambda k, v: True) Traceback (most recent call last): ... AssertionError >>> dict_filter(data, None) Traceback (most recent call last): ... AssertionError
-
octoprint.util.dict_flatten(dictionary, prefix=
''
, separator='.'
)¶ Flatten a dictionary.
- Example::
>>> data = {'a': {'a1': 'a1', 'a2': 'a2'}, 'b': 'b'} >>> expected = {'a.a1': 'a1', 'a.a2': 'a2', 'b': 'b'} >>> actual = dict_flatten(data) >>> shared = {(k, actual[k]) for k in actual if k in expected and actual[k] == expected[k]} >>> len(shared) == len(expected) True
- Parameters:¶
Returns: a flattened dict
-
octoprint.util.dict_merge(a, b, leaf_merger=
None
, in_place=False
)¶ Recursively deep-merges two dictionaries.
Based on https://www.xormedia.com/recursively-merge-dictionaries-in-python/
Example:
>>> a = dict(foo="foo", bar="bar", fnord=dict(a=1)) >>> b = dict(foo="other foo", fnord=dict(b=2, l=["some", "list"])) >>> expected = dict(foo="other foo", bar="bar", fnord=dict(a=1, b=2, l=["some", "list"])) >>> dict_merge(a, b) == expected True >>> dict_merge(a, None) == a True >>> dict_merge(None, b) == b True >>> dict_merge(None, None) == dict() True >>> def leaf_merger(a, b): ... if isinstance(a, list) and isinstance(b, list): ... return a + b ... raise ValueError() >>> result = dict_merge(dict(l1=[3, 4], l2=[1], a="a"), dict(l1=[1, 2], l2="foo", b="b"), leaf_merger=leaf_merger) >>> result.get("l1") == [3, 4, 1, 2] True >>> result.get("l2") == "foo" True >>> result.get("a") == "a" True >>> result.get("b") == "b" True >>> c = dict(foo="foo") >>> dict_merge(c, {"bar": "bar"}) is c False >>> dict_merge(c, {"bar": "bar"}, in_place=True) is c True
- octoprint.util.dict_minimal_mergediff(source, target)¶
Recursively calculates the minimal dict that would be needed to be deep merged with a in order to produce the same result as deep merging a and b.
Example:
>>> a = dict(foo=dict(a=1, b=2), bar=dict(c=3, d=4)) >>> b = dict(bar=dict(c=3, d=5), fnord=None) >>> c = dict_minimal_mergediff(a, b) >>> c == dict(bar=dict(d=5), fnord=None) True >>> dict_merge(a, c) == dict_merge(a, b) True
- octoprint.util.dict_sanitize(a, b)¶
Recursively deep-sanitizes
a
based onb
, removing all keys (and associated values) froma
that do not appear inb
.Example:
>>> a = dict(foo="foo", bar="bar", fnord=dict(a=1, b=2, l=["some", "list"])) >>> b = dict(foo=None, fnord=dict(a=None, b=None)) >>> expected = dict(foo="foo", fnord=dict(a=1, b=2)) >>> dict_sanitize(a, b) == expected True >>> dict_clean(a, b) == expected True
- Parameters:¶
- Results:
dict: A new dict based on
a
with all keys (and corresponding values) found inb
removed.
- class octoprint.util.fallback_dict(custom, *fallbacks)¶
- items() a set-like object providing a view on D's items ¶
- keys() a set-like object providing a view on D's keys ¶
- values() an object providing a view on D's values ¶
- octoprint.util.filter_non_ascii(line)¶
Filter predicate to test if a line contains non ASCII characters.
- octoprint.util.get_bom(filename, encoding)¶
Check if the file has a BOM and if so return it.
- Params:
filename (str): The file to check. encoding (str): The encoding to check for.
- Returns:¶
(bytes) the BOM or None if there is no BOM.
-
octoprint.util.get_exception_string(fmt=
"{type}: '{message}' @ {file}:{function}:{line}"
)¶ Retrieves the exception info of the last raised exception and returns it as a string formatted as
<exception type>: <exception message> @ <source file>:<function name>:<line number>
.
- octoprint.util.get_formatted_datetime(d)¶
Formats a datetime instance as “YYYY-mm-dd HH:MM” and returns the resulting string.
- Parameters:¶
- d : datetime.datetime¶
The datetime instance to format
- Returns:¶
The datetime formatted as “YYYY-mm-dd HH:MM”
- Return type:¶
string
- octoprint.util.get_formatted_size(num)¶
Formats the given byte count as a human readable rounded size expressed in the most pressing unit among B(ytes), K(ilo)B(ytes), M(ega)B(ytes), G(iga)B(ytes) and T(era)B(ytes), with one decimal place.
- octoprint.util.get_formatted_timedelta(d)¶
Formats a timedelta instance as “HH:MM:ss” and returns the resulting string.
- Parameters:¶
- d : datetime.timedelta¶
The timedelta instance to format
- Returns:¶
The timedelta formatted as “HH:MM:ss”
- Return type:¶
string
- octoprint.util.get_fully_qualified_classname(o)¶
Returns the fully qualified class name for an object.
Based on https://stackoverflow.com/a/2020083
- octoprint.util.is_allowed_file(filename, extensions)¶
Determines if the provided
filename
has one of the suppliedextensions
. The check is done case-insensitive.
-
octoprint.util.pending_deprecation(message, stacklevel=
1
, since=None
, includedoc=None
, extenddoc=False
)¶ A decorator for methods pending deprecation. Logs a pending deprecation warning via Python’s :mod:`warnings module including the supplied
message
. The call stack level used (for adding the source location of the offending call to the warning) can be overridden using the optionalstacklevel
parameter. If bothsince
andincludedoc
are provided, a deprecation warning will also be added to the function’s docstring by providing or extending its__doc__
property.- Parameters:¶
- message : string¶
The message to include in the deprecation warning.
- stacklevel : int¶
Stack level for including the caller of the offending method in the logged warning. Defaults to 1, meaning the direct caller of the method. It might make sense to increase this in case of the function call happening dynamically from a fixed position to not shadow the real caller (e.g. in case of overridden
getattr
methods).- extenddoc : boolean¶
If True the original docstring of the wrapped function will be extended by the deprecation message, if False (default) it will be replaced with the deprecation message.
- includedoc : string¶
Message about the deprecation to include in the wrapped function’s docstring.
- since : string¶
Version since when the function was deprecated, must be present for the docstring to get extended.
- Returns:¶
The wrapped function with the deprecation warnings in place.
- Return type:¶
function
- octoprint.util.pp(value)¶
>>> pp(dict()) 'dict()' >>> pp(dict(a=1, b=2, c=3)) 'dict(a=1, b=2, c=3)' >>> pp(set()) 'set()' >>> pp({"a", "b"}) "{'a', 'b'}" >>> pp(["a", "b", "d", "c"]) "['a', 'b', 'd', 'c']" >>> pp(("a", "b", "d", "c")) "('a', 'b', 'd', 'c')" >>> pp("foo") "'foo'" >>> pp([dict(a=1, b=2), {"a", "c", "b"}, (1, 2), None, 1, True, "foo"]) "[dict(a=1, b=2), {'a', 'b', 'c'}, (1, 2), None, 1, True, 'foo']"
-
octoprint.util.serialize(filename, data, encoding=
'utf-8'
, compressed=True
)¶ Serializes data to a file
In the current implementation this uses json.dumps.
If compressed is True (the default), the serialized data put through zlib.compress.
Supported data types are listed at the bottom of
octoprint.util.comprehensive_json()
, and include some data types that are not supported by json.dumps by default.This is not thread-safe, if concurrent access is required, the caller needs to ensure that only one thread is writing to the file at any given time.
-
octoprint.util.to_bytes(s_or_u: str | bytes, encoding: str =
'utf-8'
, errors: str ='strict'
) bytes ¶ Make sure
s_or_u
is a byte string.
-
octoprint.util.to_native_str(s_or_u: str | bytes, encoding: str =
'utf-8'
, errors: str ='strict'
) str ¶ Deprecated since version 1.8.0: to_native_str is no longer needed, use to_unicode instead
-
octoprint.util.to_str(s_or_u: str | bytes, encoding: str =
'utf-8'
, errors: str ='strict'
) bytes ¶ Deprecated since version 1.3.11: to_str has been renamed to to_bytes and in a future version will become the new to_unicode
-
octoprint.util.to_unicode(s_or_u: str | bytes, encoding: str =
'utf-8'
, errors: str ='strict'
) str ¶ Make sure
s_or_u
is a string (str).
-
octoprint.util.variable_deprecated(message, stacklevel=
1
, since=None
, includedoc=None
, extenddoc=False
)¶ A function for deprecated variables. Logs a deprecation warning via Python’s :mod:`warnings module including the supplied
message
. The call stack level used (for adding the source location of the offending call to the warning) can be overridden using the optionalstacklevel
parameter.- Parameters:¶
- message : string¶
The message to include in the deprecation warning.
- stacklevel : int¶
Stack level for including the caller of the offending method in the logged warning. Defaults to 1, meaning the direct caller of the method. It might make sense to increase this in case of the function call happening dynamically from a fixed position to not shadow the real caller (e.g. in case of overridden
getattr
methods).- since : string¶
Version since when the function was deprecated, must be present for the docstring to get extended.
- Returns:¶
The value of the variable with the deprecation warnings in place.
- Return type:¶
value
-
octoprint.util.variable_pending_deprecation(message, stacklevel=
1
, since=None
, includedoc=None
, extenddoc=False
)¶ A decorator for variables pending deprecation. Logs a pending deprecation warning via Python’s :mod:`warnings module including the supplied
message
. The call stack level used (for adding the source location of the offending call to the warning) can be overridden using the optionalstacklevel
parameter.- Parameters:¶
- message : string¶
The message to include in the deprecation warning.
- stacklevel : int¶
Stack level for including the caller of the offending method in the logged warning. Defaults to 1, meaning the direct caller of the method. It might make sense to increase this in case of the function call happening dynamically from a fixed position to not shadow the real caller (e.g. in case of overridden
getattr
methods).- since : string¶
Version since when the function was deprecated, must be present for the docstring to get extended.
- Returns:¶
The value of the variable with the deprecation warnings in place.
- Return type:¶
value
octoprint.util.commandline¶
- class octoprint.util.commandline.CommandlineCaller¶
The CommandlineCaller is a utility class that allows running command line commands while logging their stdout and stderr via configurable callback functions.
Callbacks are expected to have a signature matching
def callback(*lines): do_something_with_the_passed_lines()
The class utilizes sarge underneath.
Example:
from octoprint.util.commandline import CommandLineCaller, CommandLineError def log(prefix, *lines): for line in lines: print("{} {}".format(prefix, line)) def log_stdout(*lines): log(">>>", *lines) def log_stderr(*lines): log("!!!", *lines) def log_call(*lines) log("---", *lines) caller = CommandLineCaller() caller.on_log_call = log_call caller.on_log_stdout = log_stdout caller.on_log_stderr = log_stderr try: caller.checked_call(["some", "command", "with", "parameters"]) except CommandLineError as err: print("Command returned {}".format(err.returncode)) else: print("Command finished successfully")
-
call(command: str | list[str] | tuple[str], delimiter: bytes =
b'\n'
, buffer_size: int =-1
, logged: bool =True
, output_timeout: float =0.5
, **kwargs) tuple[int | None, list[str], list[str]] ¶ Calls a command
- checked_call(command: str | list[str] | tuple[str], **kwargs) tuple[int, list[str], list[str]] ¶
Calls a command and raises an error if it doesn’t return with return code 0
- on_log_call¶
Callback for the called command line
- on_log_stderr¶
Callback for stderr output
- on_log_stdout¶
Callback for stdout output
-
call(command: str | list[str] | tuple[str], delimiter: bytes =
- exception octoprint.util.commandline.CommandlineError(returncode, stdout, stderr)¶
Raised by
checked_call()
on non zero return codes
- octoprint.util.commandline.clean_ansi(line: str | bytes) str | bytes ¶
Removes ANSI control codes from
line
.Note: This function also still supports an input of
bytes
, leading to anoutput
ofbytes
. This if for reasons of backwards compatibility only, should no longer be used and considered to be deprecated and to be removed in a future version of OctoPrint. A warning will be logged.Changed in version 1.8.0: Usage as
clean_ansi(line: bytes) -> bytes
is now deprecated and will be removed in a future version of OctoPrint.
octoprint.util.platform¶
This module bundles platform specific flags and implementations.
-
octoprint.util.platform.CLOSE_FDS =
True
¶ Default setting for close_fds parameter to Popen/sarge.run.
Set
close_fds
on every sub process to this to ensure file handlers will be closed on child processes on platforms.
- octoprint.util.platform.get_os()¶
Returns a canonical OS identifier.
Currently the following OS are recognized:
win32
,linux
(sys.platform
=linux*
),macos
(sys.platform
=darwin
),freebsd
(sys.platform
=freebsd*
) andandroid
(sys.platform
=android
).- Returns:¶
(str) mapped OS identifier
-
octoprint.util.platform.is_os_compatible(compatibility_entries, current_os=
None
)¶ Tests if the
current_os
orsys.platform
are blacklisted or whitelisted incompatibility_entries
- Returns:¶
(bool) True if the os is compatible, False otherwise