util.utils module¶
Miscellaneous utility functions.
Created on Oct 14, 2024
Code author: Rob Kremer <robkremer@me.com>
- util.utils.makeParserFromFunc(fn: ~typing.Callable, ignoreParam: ~typing.Callable[[str], bool] = <function <lambda>>, parser: ~argparse.ArgumentParser | None = None, typeHandlers: dict[str, ~typing.Callable[[str], ~typing.Any]] = {}) ArgumentParser¶
- Parameters:
fn (Callable) – The function to make a parser for.
ignoreParam (Callable[[str], bool]) – A filter that, given the name of a parameter return True iff the param SHOULD be ignored. By default, all params will be used.
parser (argparse.ArgumentParser) – If specified, this parser will have the params of fn added. If parser is absent, a new
argparse.ArgumentParserwill be created.typeHandlers (dict[str, Callable[[str], Any]])
- Returns:
The parser.
- Return type:
argparse.ArgumentParser
Limitations to be aware of:
Complex annotations (list[int], Optional[str], unions) need extra handling
*args/**kwargsdon’t map cleanly to argparse
But for straightforward typed functions it works well.
- util.utils.resolveAliases(x: str, table: dict[str, str], raiseOnError: bool = True) str¶
- Parameters:
x – The string to analyze.
table – The dict from which to lookup keys in.
raiseOnError – If True a syntax error or a failed lookup in table will raise an exception, otherwise the $ expression will be left intact.
From a string, substitute any contained <key> expressions “${<key>}” for dict[“key”]. Eg: x == “a${b}c” and table == {“b”:”BB”} returns “aBBc”.
- Returns:
- Return type:
str
- util.utils.splitOnSeparator(s: str, separator: str = '.') List[str]¶
Split a string on ‘.’ while respecting single- and double-quoted substrings.
Dots inside quoted regions are treated as literal characters and do not trigger a split. Quotes are stripped from the output tokens. A quoted region must span an entire token — a quote may only open at the start of a token and must close at the end of a token (immediately before a ‘.’ or end of string). Nested quotes of the opposite kind are allowed inside a quoted region.
- Parameters:
s (str) – The input string to split.
separator (str)
- Returns:
A list of substrings split on unquoted dots, with quotes removed.
- Return type:
List[str]
- Raises:
ValueError – If a quote appears mid-token, a quoted block is not properly terminated, or characters follow a closing quote before the next ‘.’ or end of string.
- util.utils.quoteIfNecessary(s: str) str¶
If the string contains spaces return surrounded with quotes, otherwise just return the string.
- Parameters:
s (str)
- Returns:
- Return type:
str
- util.utils._CMD_MASK = 8¶
The bit of the key shortcuts are made with: Command (Mod1) on macOS, Control elsewhere (see util.platformSupport.SHORTCUT). (Not Mod1 or Mod2 off the Mac: on X11, Mod1 is Alt and Mod2 is usually Num Lock; on Windows, 0x8 is Num Lock.)
- util.utils._ALT_MASK = 16¶
The Option (Mod2) bit on macOS; Alt’s on Windows (0x20000) and on X11 (Mod1).
- util.utils.s_CMD(s: int) bool¶
- Returns:
True iff s has the Command key bit set (Control, off the Mac: the key shortcuts are made with there).
- Parameters:
s (int)
- util.utils.s_SHIFT(s: int) bool¶
- Returns:
True iff s has the Shift key bit set.
- Parameters:
s (int)
- util.utils.s_CTL(s: int) bool¶
- Returns:
True iff s has the Control key bit set.
- Parameters:
s (int)
- util.utils.s_ALT(s: int) bool¶
- Returns:
True iff s has the Alt or Option key bits set.
- Parameters:
s (int)
- util.utils.s_OPT(s: int) bool¶
- Returns:
True iff s has the Alt or Option key bits set.
- Parameters:
s (int)
- util.utils.strToBool(b: str)¶
- Parameters:
b (str)
- Returns:
- Return type:
- util.utils.WINDOWS = False¶
Whether this is Windows, where paths look like “C:folderfile” (see urlPath(), pathURL()).
- util.utils.isWindowsPath(s: str, windows: bool = False) bool¶
- Parameters:
s – A path or URL.
windows – Whether this is Windows (by default: whether it is). Elsewhere, there are no such paths: “x:/…” is a URL.
- Returns:
Whether s is a Windows path with a drive letter (eg: “C:Usersme”, “C:/Users/me”) or a network one (”\servershare...”): a path, not a URL whose scheme is one letter (as urlparse() takes it to be).
- util.utils.openFile(path: str, mode: str = 'r', **kwargs) Any¶
Like open(), but a path that can’t be a file’s (eg, one with a ‘”’ in it, on Windows, which raises an OSError “Invalid argument”) raises FileNotFoundError, as it does elsewhere: there’s no such file.
- util.utils.urlPath(url: str, windows: bool = False) str | None¶
- Parameters:
url – A “file:” URL (eg: “file:///Users/me/family.snm”, or on Windows “file:///C:/Users/me/family.snm”), or a path.
windows – Whether to make a Windows path (by default: on Windows).
- Returns:
The path of the file url is of, on this computer (“%20” is a space, …): eg: “/Users/me/family.snm”, or “C:Usersmefamily.snm” on Windows. A path is as it is (unquoted). None if url is some other URL (eg: “https:”, “sn:”).
- util.utils.pathURL(path: str, quoted: bool = True, windows: bool = False) str¶
- Parameters:
path – An absolute path.
quoted – Whether characters not allowed in URLs are quoted (eg: a space as “%20”), as Path.as_uri() does; else they’re as they are (as in “file://” + path).
windows – Whether path is a Windows path (by default: on Windows).
- Returns:
The “file:” URL of path: eg: “file:///Users/me/family.snm”, or “file:///C:/Users/me/family.snm” for “C:Usersmefamily.snm”.
- util.utils.isValidURL(url: str) bool¶
- Parameters:
url – A string to determine if it’s a proper URL
- Returns:
True iff the str appears to be well-formed URL (a Windows path, eg: “C:Usersme”, isn’t one: see isWindowsPath())
- util.utils.REMOTE_TIMEOUT = 30¶
How long (seconds) to wait for a web server (see fetchURL(), urlExists()).
- util.utils.webCacheFolder: str | None = None¶
Where copies of the files read from the web are kept, if anywhere (see fetchURL()): set by an application (eg: Semantic Nets: ~/.sn/cache).
- util.utils.cachePath(url: str) str | None¶
- Parameters:
url (str) – A web URL (“http:” or “https:”).
- Returns:
Where its copy is (or would be) in webCacheFolder – by its host, then its path (a query string, if it has one, is part of the file’s name) – or None if there’s no cache, or it isn’t a web URL.
- Return type:
str | None
- util.utils.cachedCopy(url: str) str | None¶
- Returns:
The path of url’s copy in webCacheFolder (see cachePath()), if there is one.
- class util.utils.OfflineWarning¶
Bases:
objectfetchURL()’s warnings that it’s using a cached copy: at most once per URL.
- warned: set[str] = {}¶
- util.utils.fetchURL(url: str) bytes¶
- Parameters:
url (str) – A web URL (“http:” or “https:”).
- Returns:
What’s there. It’s copied into webCacheFolder (if there is one); and if the server can’t be reached (eg: offline), that copy is used instead (with a warning).
- Return type:
bytes
- Raises:
FileNotFoundError – If there’s nothing there (HTTP 404 or 410).
urllib.error.URLError – If the server can’t be reached, and there’s no copy.
- util.utils.urlExists(url: str) bool¶
- Parameters:
url – A string to determine if it’s an existant URL
- Returns:
True iff the str is a URL that references an existant place – for a web URL whose server can’t be reached, if there’s a copy of it (see fetchURL()).
- util.utils.canWriteUrl(url: str) bool¶
- Parameters:
url (str) – A url in text format.
- Returns:
True iff you can write to that location (best guess).
- Return type:
bool
The file: check is reliable; the HTTP check is best-effort only.
- util.utils.fixURL(url: str, extension: str | None = None, replaceExt: bool | None = None, mode: str = 'w') tuple[str, ParseResult]¶
- Parameters:
url (str) – the URL to examine.
replaceExt (Optional[bool] (default: None)) – If True, any extension will be replace with the default extension; if False, the default extension will be appended to the path even there’s already another extension; if None (the default), the extension will only be added it the file does not already have an extension.
mode (str) – ‘r’ will check if the file or URL exists; ‘w’ will try to determine if the file is writable (not a URL other than a file’s, eg: “https:” – that can’t be told without writing it: it may be only for reading, so writing it fails then); anything else will make no checks.
extension (str) – The file extension to use for a replacement or appendment; if missing or None it defaults “.txt”. Ignored if replaceExt is None.
- Returns:
- Return type:
tuple[str, urllib.parse.ParseResult]
- Raises:
FileNotFoundError – if mode=”r” and the url/file does not exist for a read operation
PermissionError – if mode=”w” and the url/file doesn’t appear to be writeable.
ValueError – if the URL is empty.
Sanitize the URL by making a filename a proper “file:///” URL, dealing with the path file extension, and verifying the file is accessible for read or write.
- util.utils.fileToUrl(filename: str) str¶
- Parameters:
filename – A string representing a file path (may be relative)
- Returns:
A proper URL referencing filename; it may or may not actually exist.
- util.utils.urlToFile(url: str) str | None¶
- Parameters:
url – A string representing a URL
- Returns:
A path string equivalent to url; it may or may not actually exist.
- util.utils.openUrl(url: str) bytes¶
Fetch the contents of a URL and return them as bytes for XML parsing.
Parses the given URL to detect its scheme. For
file:URLs, the path is resolved to an absolute local path and read from the filesystem. All other schemes (e.g.http:,https:,ftp:) are fetched viaurllib.request.urlopen().The raw bytes are returned without decoding so that the XML parser can read the encoding declaration from the document itself and decode accordingly.
- Parameters:
url (str) – The URL to fetch. May use any scheme supported by
urllib.request, plus thefile:protocol for local filesystem paths.- Returns:
Raw byte content of the resource, suitable for passing directly to an XML parser (e.g.
xml.etree.ElementTree.fromstring()orlxml.etree.XMLParser).- Return type:
bytes
- Raises:
ValueError – If url is an empty string.
FileNotFoundError – If a
file:URL points to a path that does not exist.urllib.error.URLError – If a remote URL cannot be reached.
Usage:
>>> xmlBytes = openUrl("https://example.com/feed.xml") >>> import xml.etree.ElementTree as ET >>> root = ET.fromstring(xmlBytes) >>> xmlBytes = openUrl("file:///home/user/data.xml") >>> root = ET.fromstring(xmlBytes)
<adapted from Claude>
- util.utils.addDefaultExtToURL(url: str, ext: str = '.xml')¶
- Parameters:
url – a legal url.
ext – an extension to be added to <url> iff <url>’s path does not already have an extension.
- Returns:
<url> or a version of <url> with the extension added iff it did not already have an extension.
A dot is added in front of <ext> if it is not already there.
- util.utils.getNameAndExtFromURL(url: str, extension: str | None = None)¶
- Parameters:
url – a legal url, or if that fails will try to parse as a path.
extension – (default:None) if the url does not have a file extension, use this one if it’s given. If there is an extension on the URL already, extension is ignored.
- Returns:
Just the filename (no path) and extension.
- util.utils.changeUrlExtension(url, new_extension)¶
Changes the file extension of a URL.
- Args:
url (str): The original URL string. new_extension (str): The new extension (e.g., “.jpg”, “.html”).
- Returns:
str: The URL with the modified extension.
- Parameters:
url
new_extension
- Returns:
- Return type:
- util.utils.makeConcrete(abstract_cls: type[T], implementations: dict[str, Callable]) type[T]¶
Dynamically create a concrete subclass from an ABC.
- Parameters:
abstract_cls (type[T]) – The abstract base class to concretize.
implementations (dict[str, Callable]) – A mapping of abstract method names to callables.
- Returns:
A new concrete subclass with all abstract methods implemented.
- Return type:
type[T]
- Raises:
TypeError – If you left out one or more abstract methods in implementations.
Usage:¶class Shapes(ABC): @abstractmethod def area(self) -> float: ... @abstractmethod def perimeter(self) -> float: ... circle = make_concrete(Shape, { "area": lambda self: 3.14159 * 5 ** 2, "perimeter": lambda self: 2 * 3.14159 * 5, })() print(circle.area()) # 78.53975 print(circle.perimeter()) # 31.4159
- util.utils.getFullClassName(cls: type) str¶
Unlike obj.__class__.__name__ this returns the (period-deliminated) full class path of subjectClass
- Returns:
- Return type:
str
- util.utils.getClass(className: str) type | None¶
Searches the modules in the system for the first class that matches the simple class name. Use getFullyqualifiedClass() if you have a class path.
- Parameters:
className (str)
- Returns:
- Return type:
Optional[type]
- util.utils._classesByPath: dict[str, type] = {}¶
The classes getFullyQualifiedClass() has found, by their paths.
- util.utils.getFullyQualifiedClass(classPath: str) type | None¶
- Parameters:
classPath – A string representing the name of a class
- Returns:
Either a Class object or None
Follows the class path down the modules in the system to return the matching class object. User getClass() if you only have a simple class name and want to search for it. A class found is remembered (a class not found isn’t: its module may be loaded later): reading a file asks for the same few classes thousands of times, and each search looks through every module loaded.
- util.utils.getClassFromFullyQualifiedName(classPath: str) type | None¶
- Parameters:
className – A string representing the fully qualified name of a class
- Returns:
Either a Class object or None
Uses the FULLY QUALIFIED class name to retrieve the actual class.
- Parameters:
classPath (str)
- util.utils.findSubclasses(cls: Type) set[Type]¶
- Parameters:
cls – a class object to find all its loaded (imported subclasses)
- Returns:
A set of all subclasses of subjectClass
- util.utils._originOf(cls: type) type¶
Extract the bare origin type from any generic alias form.
Handles legacy
Generic[T], PEP 585list[int]-style aliases, PEP 695class Foo[T]aliases, and plain classes.
- util.utils.findConcreteSubclasses(abstractClass: Type) list[Type]¶
Return all concrete (non-abstract) subclasses of an abstract class.
Recursively walks the subclass tree, collecting any class that is not itself abstract. Handles PEP 695 (
class Foo[T]), legacyGeneric[T], and plain classes.- Parameters:
abstractClass (Type[T]) – The abstract base class to inspect, optionally parameterized.
- Returns:
A list of concrete subclass types.
- Return type:
list[Type[T]]
- util.utils.importSubmodules(packageName: str, filtr: Callable[[str], bool] | None = None) None¶
Import all modules in a package to ensure subclasses are registered.
- Parameters:
packageName (str) – The dotted package name, e.g.
'myapp.strategies'.filtr (Optional[Callable[[str], bool]]=None) – If given, the module will only be loaded if filter() called with a scanned module name returns True. If absent, all scanned modules will be imported.
- util.utils.getCallerIdInfoStr(stack: int = 1, includeArgs=True) str¶
- Parameters:
stack – An integer indicating how far back in the call stack to go. The default is 1, which indicates the caller of this method’s caller.
includeArgs (bool)
- Returns:
A string of the form “[<class>.]<method>([self=<self>]) [line <lineno>]”.
- util.utils.extendsDoc(base: type)¶
A decorator to the decorated method’s docstring its namesake’s in base, followed by its own. Works on plain methods, classmethods and staticmethods, whichever order the decorators are in. Usage:
class Sub(Base): @extendsDoc(Base) def place(self, node): """ In addition: relation labels are placed only if "place labels" is on. """ ...
- util.utils.delOne(lst: list[T], val: T, comparator: ~typing.Callable[[T, T], bool] = <function <lambda>>, throw: bool = True) bool¶
Deletes exactly one item for the list, specifically, the first one found.
- Parameters:
lst (list[T]) – The target list.
val (T) – the value to remove from the list.
comparator (Callable[[T,T],bool]) – A function to use to compare the values in the list to val. By default, is is used as the comparator.
throw (bool) – If not set to False, will raise a KeyError exception if no values that satisfy comparator(<item>, val) are found in the list. By default, this function will raise an exception if val is not found.
- Returns:
True iff item val is successfully removed from the list.
- Return type:
bool
- Raises:
KeyError – iff no item in the list matches val.
- util.utils.grouped(iterable: Iterable, n: int) Iterable[tuple[T, ...]]¶
Return an iterable of n-tuples which is a n-partition the parameter iterable:
s -> (s0,s1,s2,…sn-1), (sn,sn+1,sn+2,…s2n-1), (s2n,s2n+1,s2n+2,…s3n-1), …
Thus, list(grouped([1,2,3,4], 2)) -> [(1,2),(3,4)]
- Parameters:
iterable (Iterable[T]) – The target iterable.
n (int) – the size of the partitions, ie: the size of the tuples.
- Returns:
a iterable of n-Tuples.
- Return type:
Iterable[tuple[T,…]]
- util.utils.removeDuplicates(items: list, asTree: bool = False) list¶
Return a copy of the items list with any duplicates (determine by the “==” operator) removed. The first of any duplicates are the ones that are kept.
- Parameters:
items (list)
asTree (bool)
- Returns:
- Return type:
list
- util.utils.removeDuplicatesInPlace(items: list, removeLater=True) None¶
- Parameters:
list – The list to remove duplicates from.
removeLater – [bool, default: True] Iff True, keep the first of any duplicates, otherwise keep the last.
Removes any duplicates from the items list (determine by the “==” operator) in place.
- Parameters:
items (list)
- util.utils.flattenPairs(pairs)¶
From a vector of pairs, return a simple vector. [(1,2),(3,4)] -> [1,2,3,4]
- Parameters:
pairs
- Returns:
- Return type:
- util.utils.treeFlatten(tree: list, _omit: list = []) list¶
Flatten a tree formed by nested lists into a single flat list eliminating duplicates.
eg: [1 [2 [6], 3 [4 [6], 5 [6]]]] –> [1, 2, 6, 3, 4, 5]
- Parameters:
tree (list)
_omit (list)
- Returns:
- Return type:
list
- util.utils.treeSplit(tree: list, _omit: list = [])¶
Split a tree list into roots and the children
eg: [1 [2 [6], 3 [4 [6], 5 [6]]]] –> [1], [2 [6], 3 [4 [6], 5 [6]]] and
- [2 [6], 3 [4 [6], 5 [6]] –> [2, 3], [6, 4, 5], [6, 6] (note that [6, 4, 5] are the
immediate parents “1 in the example above)
- Parameters:
tree (list)
_omit (list)
- Returns:
- Return type:
- class util.utils.ExtendedEnumMeta(cls, bases, classdict, *, boundary=None, _simple=False, **kwds)¶
Bases:
EnumTypeA metaclass for ExtendedFlag: looking up a name with “|” in it (eg:
Flags["A|B"]) gives the combined flags.- __getitem__(name)¶
- Parameters:
name
- Returns:
- Return type:
- class util.utils.ExtendedFlag(new_class_name, /, names, *, module=None, qualname=None, type=None, start=1, boundary=None)¶
Bases:
FlagA Flag whose members can be looked up by combined names (see ExtendedEnumMeta).
- static fromStr(spec: str)¶
This cannot be right…
- Parameters:
spec (str)
- Returns:
- Return type:
- __str__() str¶
- Returns:
- Return type:
str
- static _generate_next_value_(name, start, count, last_values)¶
Generate the next value when not given.
name: the name of the member start: the initial start value or None count: the number of existing members last_values: the last value assigned or None
- _boundary_ = 'strict'¶
- _flag_mask_ = 0¶
- _singles_mask_ = 0¶
- _all_bits_ = 0¶
- _inverted_ = None¶
- util.utils.play(soundFile: str | None = None) None¶
Plays a sound file: with afplay on macOS, winsound on Windows (a .wav file), and paplay or aplay on Linux (if there’s one).
- Parameters:
soundFile –
May have the following values:
None: plays an error beep (on macOS, “/System/Library/Sounds/Sosumi.aiff”).
- Just a file name: (not containing any slashes (“/”)) on macOS, looks in
/System/Library/Sounds/ for the file.
A path: (containing slashes (“/”)) just tries to play that file.
- util.utils.xmlEscape(strXML: str) str¶
Replaces the “&”, “<”, “>”, and single and double quote characters with xml escape codes.
- Parameters:
strXML (str)
- Returns:
- Return type:
str
- util.utils.xmlUnescape(strXML: str) str¶
Replaces XML escape codes with “&”, “<”, “>”, and single and double quote characters.
- Parameters:
strXML (str)
- Returns:
- Return type:
str
- util.utils.xmlToStringIndented(elem: Element, **kwargs)¶
Emulate an ElementTree.tostring() function, but with indents similar to what you get with the ElementTree.indent() method only for Elements.
- Parameters:
elem (Element)
kwargs
- Returns:
- Return type:
- util.utils.PointIndici¶
Use this globally to choose if Points and Rects store indices as int or float values.
- class util.utils.Point(x: float, y: float)¶
- class util.utils.Point(pair: Iterable[float])
Bases:
SequenceImplementation of an (x,y) point in a flexible but constrained way. Whether indices are int or float depends on the value of PointIndici.
- __init__(x: float, y: float) None¶
- __init__(pair: Iterable[float]) None
Overloaded constructor that will take either to PointInidici arguments as x and y, or any Iterator of two PointInidicis.
- Parameters:
args
- __getitem__(index: int) float¶
- __getitem__(index: slice[Any, Any, Any], /) Sequence[float]
Implementation of indexing ([]). Works exactly like tuple*[index] where index may be an int or a slice.
- Parameters:
index (Union[int, slice[Any, Any, Any]])
- Returns:
- Return type:
Union[PointIndici, Sequence[PointIndici]]
- asTuple() tuple¶
Returns self as a tuple.
- Returns:
- Return type:
tuple
- asList() list¶
Returns self as a list.
- Returns:
- Return type:
list
- moveBy(x: float | None = None, y: float | None = None)¶
Mutating version of adding the corresponding values of x and y
- Parameters:
x (Optional[PointIndici])
y (Optional[PointIndici])
- __str__() str¶
Return the in “(<x>,<y>)” form.
- Returns:
- Return type:
str
- _abc_impl = <_abc._abc_data object>¶
- util.utils.pointInRect(pt: Iterable[float], rect: Iterable[float]) bool¶
- Parameters:
pt – (x,y)
rect – (x,y,x1,y1)
- Returns:
True iff the give pt lies inside rect.
- util.utils.shiftRectToPoint(rect: Iterable[float], point: Iterable[float]) list[float]¶
- Parameters:
pt – (x,y)
rect – (x,y,x1,y1)
point (Iterable[PointIndici])
- Returns:
A new rectangle if the same size and aspect ratio as rect, but with the upper left corner at pt
- util.utils.overlaps(rect1: Iterable[float], rect2: Iterable[float]) bool¶
- Parameters:
rect1 – (x,y,x1,y1)
rect2 – (x,y,x1,y1)
- Returns:
True iff the two rectangles overlap.
- util.utils.pointInPoly(pt: Iterable[float], poly: Iterable[float]) bool¶
- Parameters:
pt – (x,y)
poly – (x,y [,x1,y1]…)
- Returns:
True iff the give pt lies inside poly.
- util.utils.midpoint(*pts: Iterable[float]) Tuple[float, float]¶
- Parameters:
pts – A list of point pairs
- Returns:
The point midway between all the pts
- util.utils.expandRect(rect: Iterable[float], spacing: Iterable[float] | float) list[float]¶
- Parameters:
rect – The rectangle to expand.
spacing – The vector of points to expand rect as [left, top, right, bottom]. May be of length 1, 2, or 4 or an int or a float, with the obvious interpretations.
- Returns:
A new rectangle representing the expansion of rect
- util.utils.normalizeRect(rect: Iterable[float]) list[float]¶
Fix up a rect (x,y,x1,y1) such that x<x1 and y<y1, in conformance to tk rules.
- Param:
rect:
- Returns:
A new rectangle same as rect, but s/t x<x1 and y<y1.
- Parameters:
rect (Iterable[PointIndici])
- util.utils.iterableToList(it: Iterable) list¶
- Parameters:
it (Iterable)
- Returns:
- Return type:
list
- util.utils.getSubMenu(menu: Menu, name: str, makeIfNone: int | str | None = 'end') Menu | None¶
Find a submenu in menu with label name .
- Parameters:
menu – The menu to search
name – The label of the item we are searching for
makeIfNone – [default: tk.END (insert at end)] if not None and menu does not contain any menu items named name then insert a new menu named name at position makeIfNone – either an int index or one of Tkinter’s symbolic index constants (e.g. tk.END, which is itself just the str “end”; this is what insert_cascade() itself accepts, so we just pass it straight through).
- Returns:
Return a tk.Menu if it is found or created; if it is not found and makeIfNone is None, return None .
- util.utils.getToplevelWindows(root: Tk)¶
root’s top-level windows.
- util.utils.getMenuBar() Menu | None¶
Resolve the app’s menu bar – the configured menu of
tk._default_root.- Returns:
The resolved tk.Menu, or None if there’s no default root, or it has no menu bar configured.
- util.utils._findEntry(menu: Menu, label: str) tuple[int | None, str | None]¶
- Parameters:
menu – The menu to search.
label – The label of the item we are searching for.
- Returns:
(index, type) of the entry in menu labelled label, or (None, None) if there is no such entry.
- util.utils._separatedItems: set[tuple[str, str]] = {}¶
(menu, label) of the items added with a separator just above them (see addToMenuBar()’s separatorBefore).
- util.utils._separate(menu: Menu, label: str, separatorBefore: bool) None¶
If separatorBefore: make sure the item labelled label in menu has a separator just above it (unless it’s the first), and note that it’s the item’s, to go with it (see removeFromMenuBar()).
- Parameters:
menu – The menu.
label – The item’s label.
separatorBefore – Whether it has a separator above it.
- util.utils._lastItems: set[tuple[str, str]] = {}¶
(menu, label) of the items kept at the end of their menus (see keepLast()).
- util.utils.keepLast(menu: Menu, *labels: str) None¶
Keep the items labelled labels in menu at its end: items addToMenuBar() and addCheckToMenuBar() add later go above them (and above the separator just above them, if there is one) – eg: “Quit” at the end of a File menu.
- Parameters:
menu – The menu.
labels – Its items’ labels.
- util.utils._endIndex(menu: Menu) int | str¶
- Returns:
Where a new item goes at the end of menu: tk.END, or above the items kept last (see keepLast()).
- util.utils.addToMenuBar(path: str, command: Callable | None = None, *, menu: Menu | None = None, accelerator: str | None = None, cascadePositions: dict[str, int] | None = None, separatorBefore: bool = False) None¶
Add – or, if already present, replace – an entry in the app’s menu bar.
Pass exactly one of command or menu: command adds/replaces a plain command entry that invokes command when chosen; menu adds/replaces a cascade entry whose submenu is menu. The top-level menu bar itself is always the app’s own – resolved from
tk._default_root’s configured menu (see getMenuBar()) – there’s no need to look it up and pass it in.- Parameters:
path – A
"|"-separated path of cascade labels ending in the item’s own label, e.g."File|Save view". All but the last segment name cascade submenus, created via getSubMenu() if they don’t already exist; the last segment is the item’s own label.command – The callable to invoke when the item is chosen. Give this to add/replace a plain command item; mutually exclusive with menu.
menu – The submenu to show as a cascade. Give this to add/replace a cascade item; mutually exclusive with command.
accelerator – Optional accelerator string to display (e.g. “Cmd+S”).
cascadePositions – Where to put any cascade that has to be made, by label, eg:
{"Edit": 1}; by default, at the end (as for addCheckToMenuBar()).separatorBefore – Put a separator just above the item (unless it’s the first, or there’s one there already): it starts a group of items. removeFromMenuBar() removes the separator with the item.
- Note:
Safe to call repeatedly with the same path – e.g. every time a window gains focus – since an existing entry with the same final label is reconfigured in place rather than duplicated (and, if it was previously the other kind of entry – command vs. cascade – it’s replaced in place, at the same position). So a window can add its items unconditionally whenever it gains focus.
- util.utils.addCheckToMenuBar(path: str, variable: Variable, command: Callable | None = None, *, cascadePositions: dict[str, int] | None = None, separatorBefore: bool = False) None¶
Add – or, if already present, replace – a check item in the app’s menu bar: it shows (and sets) the boolean variable, and calls command when chosen. Like addToMenuBar(), safe to call repeatedly with the same path (eg: each time a window gains focus, rebinding it to that window’s variable), and removed with removeFromMenuBar().
- Parameters:
path – A
"|"-separated path of cascade labels ending in the item’s own label, e.g."View|Animation toolbar".variable – The (boolean) variable the item shows and sets.
command – Called (after variable is set) when the item is chosen.
cascadePositions – Where to put any cascade that has to be made, by label, eg:
{"View": 1}(just after “File”); by default, at the end.separatorBefore – As for addToMenuBar().
- util.utils.removeFromMenuBar(path: str) None¶
Remove an entry (as added by addToMenuBar()) from the app’s menu bar – and the separator above it, if it was added with one (separatorBefore).
Safe to call even when the item (or an intervening cascade) isn’t currently present – this is simply a no-op in that case, so callers (eg: a window’s focus-out handler) don’t need to track whether they actually added the item first.
- Parameters:
path – Same
"|"-separated path as passed to addToMenuBar().
- util.utils.isGuiAvailable() bool¶
Determine whether a graphical display environment appears to be available.
- Returns:
True if a GUI environment is likely usable, False otherwise.
- Return type:
bool
- util.utils.askViaTk(prompt: str, title: str = 'Input required', check: ~typing.Callable[[str], bool] = <function <lambda>>) str | None¶
Prompt the user for input using a Tkinter dialog: in the running Tk application, if there is one (over its focused window); otherwise in a Tk interpreter of its own, made for it and destroyed afterwards.
- Parameters:
prompt (str) – The message to display to the user.
title (str) – The dialog window title.
- Returns:
The user’s input, or None if the dialog could not be created or was cancelled.
- Return type:
Optional[str]
- util.utils.askViaTerminal(prompt: str, check: ~typing.Callable[[str], bool] = <function <lambda>>) str | None¶
Prompt the user for input via stdin/stdout.
- Parameters:
prompt (str) – The message to display to the user.
- Returns:
The user’s input, or None if stdin is not interactive.
- Return type:
Optional[str]
- util.utils.askYesNo(question: str, title: str) bool¶
Ask the user a yes-or-no question: in a Yes/No dialog over the focused window, if the GUI is running; otherwise (eg: the terminal interface, or once the windows are gone at exit) as text (see util.utils.askUser()).
- Parameters:
question (str)
title (str) – The dialog’s title.
- Returns:
True iff the answer is yes.
- Return type:
bool
- util.utils.askUser(prompt: str, title: str = 'Input required', check: ~typing.Callable[[str], bool] = <function <lambda>>) str | None¶
Ask the user a question, using a GUI dialog if available and falling back to the terminal.
- Parameters:
prompt (str) – The message to display to the user.
title (str) – The dialog window title, used only in GUI mode.
check (check:Callable[[str],bool]) – A function to validate user input.
- Returns:
The user’s input, or None if no input method succeeded.
- Return type:
Optional[str]
- class util.utils.VerticalScrolledFrame(parent, *args, **kw)¶
Bases:
FrameA pure Tkinter scrollable frame that actually works! * Use the ‘interior’ attribute to place widgets inside the scrollable frame. * Construct and pack/place/grid normally. * This frame only allows vertical scrolling.
- __init__(parent, *args, **kw)¶
A frame that scrolls vertically: put widgets in its interior.
- util.utils.wheelSteps(event: Event) int¶
- Parameters:
event – A mouse wheel event (see wheelEvents()).
- Returns:
How far it goes, in the wheel’s steps: positive up (away from the user), negative down. On macOS, Tk’s delta (a trackpad’s small steps); on Windows and X11, delta / 120 (a notch), at least 1 either way; for X11’s buttons 4 and 5 (Tk before 8.7), 1 and -1.
- util.utils.wheelEvents(shift: bool = False) list[str]¶
- Parameters:
shift – The events with Shift held (on most systems, a sideways scroll).
- Returns:
The event sequences a mouse wheel makes, to bind: “<MouseWheel>”; and with Tk before 8.7 on X11, where the wheel is buttons 4 and 5, “<Button-4>” and “<Button-5>” too. (See wheelSteps().)
- util.utils.bindRightMouse(window, func)¶
Bind func to a right click in window: also Control-click, on macOS.
- util.utils.tag_bindRightMouse(window, id_, func)¶
Bind func to a right click on canvas item id_ (see bindRightMouse()).
- util.utils.tag_unbindRightMouse(window, id_)¶
Unbind a right click on canvas item id_ (see tag_bindRightMouse()).
- util.utils.eventEqual(e1, e2)¶
Whether e1 and e2 are the same event: of the same type, at the same place on the screen.
- util.utils.dialogOwner(parent: Any) Misc | None¶
- Parameters:
parent (tk.Misc | tk.Wm | None) – What a dialog is opened from (any widget), if anything.
- Returns:
The window the dialog belongs over: parent’s own window, if it’s on screen; else the app’s window that has the focus, or failing that one that’s full screen, or any that’s on screen – eg: when parent is an app’s hidden root window; or None if none is.
- Return type:
tk.Misc | None
- util.utils.ownDialog(dialog: Toplevel, parent: Any) None¶
Make dialog transient for the window it belongs over (see dialogOwner()): it’s then shown over that window, at its own size. Call it before dialog is first shown: on macOS, a window that isn’t transient for another opens full screen – in a space of its own – when the app’s in full screen, and making it transient once it’s been shown doesn’t undo that. (Never transient for a window that isn’t on screen: on macOS/Aqua that can leave the dialog blank, or never shown: see showExceptionDialog().)
- Parameters:
dialog (tk.Toplevel) – A dialog: a new window, not shown yet.
parent (tk.Misc | tk.Wm | None) – What it’s opened from, if anything.
- util.utils.showExceptionDialog(parent: Toplevel | Tk | None = None, title: str = 'Error', text: str | None = None) None¶
Display the currently-handled exception’s traceback (as returned by traceback.format_exc()) in a scrollable, resizable dialog. Call this from within an except: block, the same place you’d call traceback.print_exc().
- Parameters:
parent (tk.Misc | None) – The parent widget/window this dialog is transient to.
title (str) – The dialog’s window title.
text (str) – The full text of the traceback (presumably form traceback.format_exc()).
- Return type:
None
- util.utils.allSubclasses(cls) set¶
Returns the set of all descendants of subjectClass
- Returns:
- Return type:
set
- util.utils.allConcreteSubclasses(cls) set¶
Returns the set of all non-abstract descendants of subjectClass
- Returns:
- Return type:
set
- class util.utils.Categories¶
Bases:
GenericNamed categories of objects, each defined by a test: isCategory() says whether an object is in any of the named categories.
- __init__()¶
- categories: dict[str, Callable[[T], bool]]¶
- addCategory(name: str, test: Callable[[T], bool])¶
- Parameters:
name (str)
test (Callable[[T], bool])
- deleteCategory(name: str)¶
- Parameters:
name (str)
- isCategory(obj: T, categories: Iterable[str] | str)¶
- Parameters:
obj (T)
categories (Union[Iterable[str], str])
- Returns:
- Return type:
- keys()¶
- Returns:
- Return type: