bubop package
Submodules
bubop.arg_parser module
Argparse-related utilities.
- bubop.arg_parser.add_bool_argument(parser: ArgumentParser, arg_name: str, default: bool | None = None, true_help: str | None = None)
Add a boolean CLI argument to the given ArgumentParser object.
The flag defaults to False if no other is specified
Usage:
>>> import argparse >>> parser = argparse.ArgumentParser(description="SomeArgumentParser") >>> add_bool_argument(parser, "someflag") >>> add_bool_argument(parser, "someflag2", default=True) >>> add_bool_argument(parser, "someflag3", default=False) >>> add_bool_argument(parser, "someflag4", true_help="somehelp4") >>> add_bool_argument(parser, "a_flag") >>> add_bool_argument(parser, "b-flag") >>> config = parser.parse_args(["--someflag"]) # basic >>> config.someflag True >>> config = parser.parse_args(["--no-someflag"]) >>> config.someflag False >>> config = vars(parser.parse_args([])) # defaults >>> config["someflag"] == False True >>> config["someflag2"] == True True >>> config["someflag3"] == False True >>> config["someflag4"] == False True >>> "somehelp4" in parser.format_help() True >>> parser.parse_args(["--someflag", "--no-someflag"]) # exception Traceback (most recent call last): ... SystemExit: 2 >>> config = vars(parser.parse_args(["--a_flag"])) >>> config["a_flag"] == True True >>> config = vars(parser.parse_args(["--b-flag"])) >>> config["b-flag"] == True True
bubop.classes module
Class and metaclass-related utilities.
- bubop.classes.all_subclasses(cls: type[Any]) set[type[Any]]
Recursively get all the (reachable) subclasses of the given class.
Usage:
>>> class Foo: pass >>> class Bar(Foo): pass >>> class Baz(Foo): pass >>> class Bing(Bar): pass >>> sorted([c.__name__ for c in all_subclasses(Foo)]) ['Bar', 'Baz', 'Bing']
bubop.cli module
CLI-related utilities.
- bubop.cli.check_optional_mutually_exclusive(arg1: Any, arg2: Any) None
Check if the given mutually exclusive args indeed hold the said required rule (optional + mutual exclusivity)
Raise a CliIncompatibleOptionsError if they don’t uphold the rule.
>>> kalimera = 1 >>> kalinuxta = 2 >>> check_optional_mutually_exclusive(kalimera, kalinuxta) Traceback (most recent call last): bubop.exceptions.CliIncompatibleOptionsError: ... kalimera ... kalinuxta ... >>> kalimera = None >>> check_optional_mutually_exclusive(kalimera, kalinuxta) == None True >>> kalinuxta = None >>> check_optional_mutually_exclusive(kalimera, kalinuxta) == None True
- bubop.cli.check_required_mutually_exclusive(arg1: Any, arg2: Any, arg1_name: str, arg2_name: str) None
Check if the given mutually exclusive args indeed hold the said required rule (required + mutual exclusivity)
Raise exception if they don’t uphold the rule.
bubop.common_dir module
Home of the CommonDir class.
bubop.crypto module
Cryptography-related utilities.
- bubop.crypto.read_gpg_token(p: Path, timeout_secs: int = 3) str
Read the token from a gpg file.
Raise a RuntimeError if the decryption was unsuccessful.
- bubop.crypto.write_gpg_token(p: Path, token: str, recipient: str) None
Write the given token to a gpg file designated by p.
Raise a RuntimeError if the encryption was unsuccessful.
bubop.exceptions module
Custom Exceptions.
- exception bubop.exceptions.ApplicationNotInstalled(appname: str)
Bases:
BaseExceptionException raised when a required application is not installed on the system.
- exception bubop.exceptions.AtLeastNOptionsRequired(*args, **kargs)
Bases:
NOptionsRequiredAtLeastNOptionsRequired exception.
Usage:
>>> raise AtLeastNOptionsRequired(num_required=2, foo="bar", baz="bing") Traceback (most recent call last): bubop.exceptions.AtLeastNOptionsRequired: At least 2 of the following arguments are required: ...
- exception bubop.exceptions.AuthenticationError(appname: str)
Bases:
BaseExceptionException raised when authentication with a certain application/service failed
- exception bubop.exceptions.CliIncompatibleOptionsError(opt1: Any, opt2: Any)
Bases:
BaseExceptionException raised when incompatible options are given in the CLI of a program.
Usage:
>>> raise CliIncompatibleOptionsError("foo", "bar") Traceback (most recent call last): bubop.exceptions.CliIncompatibleOptionsError: Provided option groups foo and bar are incompatible with each other
- exception bubop.exceptions.Exactly1OptionRequired(*args, **kargs)
Bases:
ExactlyNOptionsRequiredExactly1OptionRequired exception.
Usage:
>>> raise Exactly1OptionRequired(num_given=0, foo="bar", baz="bing") Traceback (most recent call last): bubop.exceptions.Exactly1OptionRequired: Exactly 1 of the following arguments are required: ...
- exception bubop.exceptions.ExactlyNOptionsRequired(*args, **kargs)
Bases:
NOptionsRequiredExactlyNOptionsRequired exception.
Usage:
>>> raise ExactlyNOptionsRequired(num_required=2, foo="bar", baz="bing") Traceback (most recent call last): bubop.exceptions.ExactlyNOptionsRequired: Exactly 2 of the following arguments are required: ...
- exception bubop.exceptions.NOptionsRequired(prefix: str, num_required: int, *args, num_given: int | None = None, **kargs)
Bases:
BaseExceptionException raised when at least N of the given options were required
- exception bubop.exceptions.NoSuchFileOrDirectoryError(name)
Bases:
BaseExceptionException raised when file/directory is not found.
Usage:
>>> raise NoSuchFileOrDirectoryError("foo") Traceback (most recent call last): bubop.exceptions.NoSuchFileOrDirectoryError: No such file or directory -> foo
- exception bubop.exceptions.NotEnoughArgumentsError
Bases:
BaseExceptionException raised when incompatible options are given in the CLI of a program.
Usage:
>>> raise NotEnoughArgumentsError() Traceback (most recent call last): bubop.exceptions.NotEnoughArgumentsError: ...
- exception bubop.exceptions.OperatingSystemNotSupportedError(os_name: str)
Bases:
BaseExceptionException raised when an operation is not supported for the OS at hand.
Usage:
>>> raise OperatingSystemNotSupportedError("Windows") Traceback (most recent call last): bubop.exceptions.OperatingSystemNotSupportedError: Operation is not supported for this OS -> Windows
- exception bubop.exceptions.TooShallowStackError
Bases:
BaseExceptionException raised when the stack trace does not have as many frames as expected.
bubop.exit_hooks module
Exit hooks class.
- class bubop.exit_hooks.ExitHooks(print_fn=<built-in function print>)
Bases:
objectMonkeypatch sys.exit + set the excepthook to figure out when an exception or an exit event was raised.
Set this during program execution and then, e.g., during program teardown, e.g., using atexit, figure out whether an exception was raised or whether the program exited successfully or failed.
- exc_handler(exc_type, exc_value, tb, *args)
Exception handler override.
- exit(code=0)
Exit function override.
- register()
Register the exit hook.
bubop.fs module
Filesystem-related utilities.
- class bubop.fs.FileType(*values)
Bases:
EnumEnum to represent an entity on a filesystem and abstract operations on them.
>>> ft = FileType.FILE >>> ft.exists(Path("/etc/passwd")) True >>> ft.exists(Path("/etc/")) False
>>> ft = FileType.DIR >>> ft.exists(Path("/etc/passwd")) False >>> ft.exists(Path("/etc/")) True
- DIR = 2
- FILE = 1
- FILE_OR_DIR = 3
- exists(path: Path) bool
True if the give npath exists. Uses the appropriate function for the Filepath at hand.
- bubop.fs.get_file_unique_id(p: Path) str
Get a unique identifier for the filesystem entity at hand.
Use a combination of device ID and inode.
- bubop.fs.get_valid_filename(s: str) str
Return a filename-compatible version of the given string s.
- Parameters:
s – String to be used as the base of the filename. You may also pass non-string objects that will however be able to convert to strings via the str operator.
>>> get_valid_filename(r"5678^()^") '5678____' >>> get_valid_filename(r"a|string\go/es||here") 'a_string_go_es__here' >>> get_valid_filename(r"strin***g") 'strin___g'
See also
- bubop.fs.valid_dir(s: str) Path
Return a pathlib.Path from the given string.
If the input does not correspond to a valid directory, then raise an exception
>>> valid_dir("/etc/") PosixPath... >>> valid_dir("/etc/passwd") Traceback (most recent call last): NotADirectoryError: ...
- bubop.fs.valid_file(s: str) Path
Return a pathlib.Path from the given string.
If the input does not correspond to a valid directory, then raise an exception >>> valid_file(“/etc/”) Traceback (most recent call last): FileNotFoundError: … >>> valid_file(“/etc/passwd”) PosixPath…
- bubop.fs.valid_path(s: str, filetype=FileType.FILE_OR_DIR) Path
Return a pathlib.Path from the given string.
If the input does not correspond to a valid path, then raise an exception
>>> valid_path("/etc") PosixPath... >>> valid_path("/etc/some-invalid-path") Traceback (most recent call last): bubop.exceptions.NoSuchFileOrDirectoryError: No such ...
>>> valid_path("/etc", filetype=FileType.FILE) Traceback (most recent call last): FileNotFoundError: ...
>>> valid_path("/etc/passwd", filetype=FileType.FILE) PosixPath...
>>> valid_path("/etc/passwd", filetype=FileType.DIR) Traceback (most recent call last): NotADirectoryError: ... >>> valid_path("/etc", filetype=FileType.DIR) PosixPath...
bubop.inspect module
Runtime-related utilities - making use of the inspect module.
- bubop.inspect.inspect_var_name(var: Any, level=2) str | None
Retrieve the name of the variable var passed from the caller to this function.
Use the level argument to refer to the argument name of the caller’s caller (level=2) or the caller’s caller’s caller, (level=3) etc. instead.
Quite experimental function in nature, may not work as expected.
Usage:
>>> var1 = "kalimera" >>> inspect_var_name(var1, level=1) 'var1' >>> fn = lambda x: (inspect_var_name(x, level=1), inspect_var_name(x)) >>> fn(var1) ('x', 'var1') >>> inspect_var_name(var1, level=1000) == None Traceback (most recent call last): bubop.exceptions.TooShallowStackError: Stack has less ... >>> inspect_var_name(1, level=1) == None True
bubop.logging module
Logging-oriented utilities.
- bubop.logging.log_to_syslog(name: str, level: Literal['FATAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'TRACE'] = 'WARNING')
Enable logging to syslog for the given logger.
This method does not remove any of the existing logging handlers.
- bubop.logging.loguru_set_verbosity(verbosity: int)
Set the verbosity of the tqdm logger.
- Parameters:
verbosity – 0 for >= INFO, 1 for >= DEBUG, 2 for >= TRACE
- bubop.logging.loguru_tqdm_sink(verbosity: int)
Change the default loguru logger to use tqdm.
- Parameters:
verbosity – Set the verbosity of the tqdm logger. 0 for >= INFO, 1 for >= DEBUG, 2 for >= TRACE
- bubop.logging.verbosity_int_to_std_logging_lvl(verbosity: int) int
Map an integer to a corresponding python std logging module level :param verbosity: Set the verbosity of the tqdm logger.
0 for >= INFO, 1 for >= DEBUG,
>>> verbosity_int_to_std_logging_lvl(0) 20 >>> verbosity_int_to_std_logging_lvl(1) 10 >>> verbosity_int_to_std_logging_lvl(2) 10 >>> verbosity_int_to_std_logging_lvl(3) 10 >>> verbosity_int_to_std_logging_lvl(-1) Traceback (most recent call last): RuntimeError: ...
- bubop.logging.verbosity_int_to_str(verbosity: int) Literal['FATAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'TRACE']
Map a verbosity integer to the corresponding Loguru Level. :param verbosity: = 0 -> INFO,
= 1 -> DEBUG, >=2 -> TRACE
Usage:
>>> verbosity_int_to_str(1) 'DEBUG' >>> verbosity_int_to_str(2) 'TRACE' >>> verbosity_int_to_str(3) 'TRACE' >>> verbosity_int_to_str(-1) Traceback (most recent call last): RuntimeError: ...
bubop.misc module
Miscellaneous utilities - not tied to a more specific module right now.
- bubop.misc.get_object_unique_name(obj: Any) str
Return a unique string associated with the given object.
That string is constructed as follows: <object class name>_<object_hex_id>
- bubop.misc.xor(*args) bool
True if exactly one of the arguments of the iterable is True.
>>> xor(0,1,0,) True >>> xor(1,2,3,) False >>> xor(False, False, False) False >>> xor("kalimera", "kalinuxta") False >>> xor("", "a", "") True >>> xor("", "", "") False
bubop.prefs_manager module
Home of the PrefsManager class.
- class bubop.prefs_manager.PrefsManager(app_name: str, config_fname: str = 'cfg.yaml', logger=<loguru.logger handlers=[(id=0, level=10, sink=<stderr>)]>)
Bases:
objectManage application-related preferences.
All the preferences of the app are stored in a key-value store (aka dict). You can either access this dict via the .contents property or the PrefsManager instance itself using the same methods as a standard dict (
key in prefs_managerorprefs_manager["key"]) or using them as attributes: (prefs_manager.key)- property config_directory: Path
Get the path to the top-level config directory of the preferences at hand.
- property config_file: Path
Get the path to the config file of the preferences at hand.
- empty() bool
Returns whether the current preferences store is empty.
- flush_config(p: Path)
Helper class for writing the current cached settings to a file.
- Parameters:
p – Path to write the current settings. The given file is to be overwritten
- items()
Return the items in the Preferences Manager - similar to a dict.
- keys() Sequence[Any]
Return the list of keys in the Preferences Manager
- update_latest(new_val)
Update the latest fetched setting.
- values()
Return the list of values in the Preferences Manager
bubop.serial module
Serialization utilities.
- bubop.serial.pickle_dump(item: Any, path: Path | str, *, protocol=0, **kargs)
Helper method to serialize your dictionary to the given path.
By default use protocol 0.
- bubop.serial.pickle_load(path: Path | str) Any
Pickle-load using the given path.
bubop.string module
String-related utilities.
- bubop.string.camel_case_to_dashed(s: str) str
Convert a CamelCase string into the dashed representation.
>>> camel_case_to_dashed("KalimeraKalinuxta") 'kalimera-kalinuxta' >>> camel_case_to_dashed("somethingIsRotten") 'something-is-rotten' >>> camel_case_to_dashed("SLAM") 'slam'
- bubop.string.format_dict(items: Mapping[Any, Any], align_items: bool = True, **kargs) str
Utility for formatting a dictionary - similar to print.pformat.
Accepts mostly the same arguments as format_list.
- bubop.string.format_list(items: Sequence[str], header: str, indent=2, bullet_char='-', header_sep='=', prefix: str = '', suffix: str = '') str
Format and return a string with the corresponding header and all the items each occupying a single line and with the specified indentation.
- bubop.string.get_random_string(len_=10) str
Return a random string containing ascii characters, digits and punctuation marks.
- bubop.string.non_empty(title: str, value: str, join_with: str = ' -> ', newline=True) str
Return a one-line formatted string of “title -> value” but only if value is a non-empty string. Otherwise return an empty string
>>> non_empty(title="title", value="value") 'title -> value\n' >>> non_empty(title="title", value=None) ''
bubop.test module
bubop.time module
Time-related utilities.
- class bubop.time.TimePeriod(*values)
Bases:
EnumHolds different units of measuring time.
- Day = 4
- Hour = 3
- Microsecond = 0
- Minute = 2
- Month = 5
- Second = 1
- Year = 6
- higher_or_equal_to_this() list[TimePeriod]
Return all the periods that are higher or equal than the current one.
Usage:
>>> [p.name for p in TimePeriod.Month.higher_or_equal_to_this()] ['Year', 'Month']
- higher_to_this() list[TimePeriod]
Return all the periods that are bigger than the current one.
Usage:
>>> [p.name for p in TimePeriod.Year.higher_to_this()] [] >>> [p.name for p in TimePeriod.Month.higher_to_this()] ['Year'] >>> [p.name for p in TimePeriod.Day.higher_to_this()] ['Month', 'Year']
- lower_or_equal_to_this() list[TimePeriod]
Return all the periods that are smaller or equal than the current one.
Usage:
>>> [p.name for p in TimePeriod.Microsecond.lower_or_equal_to_this()] ['Microsecond']
- lower_to_this() list[TimePeriod]
Return all the periods that are smaller than the current one.
Usage:
>>> [p.name for p in TimePeriod.Microsecond.lower_to_this()] [] >>> [p.name for p in TimePeriod.Minute.lower_to_this()] ['Microsecond', 'Second'] >>> [p.name for p in TimePeriod.Day.lower_to_this()] ['Microsecond', 'Second', 'Minute', 'Hour']
- bubop.time.assume_local_tz_if_none(dt: datetime) datetime
If there is no timezone in the given datetime object, assign a local timezone.
In all cases return a new instance of the datetime object.
Usage:
>>> dt = datetime.datetime(2019, 3, 8, 0, 29, 6) >>> dt.tzinfo is None True >>> dt = assume_local_tz_if_none(dt) >>> dt.tzinfo is None False >>> dt_old = datetime.datetime.now(tz=dateutil.tz.tzlocal()) >>> dt_old.tzinfo is not None True >>> dt = assume_local_tz_if_none(dt_old) >>> dt.tzinfo is None False
- bubop.time.format_datetime_tz(dt: datetime) str
Format a datetime object according to the ISO specifications containing the ‘T’ and ‘Z’ separators
Usage:
>>> format_datetime_tz(datetime.datetime(2019, 3, 5, 0, 3, 9, 1234)) '2019-03-05T00:03:09.001234Z' >>> format_datetime_tz(datetime.datetime(2019, 3, 5, 0, 3, 9, 123)) '2019-03-05T00:03:09.000123Z'
- bubop.time.get_datetime_up_to(period: TimePeriod, dt: datetime) datetime
Create a new date with only the parts up to the period specified. The rest are discarded.
Usage:
>>> dt = datetime.datetime(year=1, month=2, day=3, hour=4, minute=5, second=6, microsecond=7) >>> get_datetime_up_to(period=TimePeriod.Year, dt=dt) Traceback (most recent call last): TypeError: Invalid TimePeriod... >>> get_datetime_up_to(period=TimePeriod.Month, dt=dt) Traceback (most recent call last): TypeError: Invalid TimePeriod... >>> get_datetime_up_to(period=TimePeriod.Day, dt=dt) datetime.datetime(1, 2, 3, 0, 0) >>> get_datetime_up_to(period=TimePeriod.Hour, dt=dt) datetime.datetime(1, 2, 3, 4, 0) >>> get_datetime_up_to(period=TimePeriod.Minute, dt=dt) datetime.datetime(1, 2, 3, 4, 5) >>> get_datetime_up_to(period=TimePeriod.Second, dt=dt) datetime.datetime(1, 2, 3, 4, 5, 6) >>> get_datetime_up_to(period=TimePeriod.Microsecond, dt=dt) == dt True
- bubop.time.is_same_datetime(dt1: datetime, dt2: datetime, tol: timedelta = datetime.timedelta(0)) bool
Compare two datetime.datetime objects.
If the timezone is empty, assume local timezone.
Usage:
>>> dt = datetime.datetime >>> td = datetime.timedelta >>> dt1 = datetime.datetime.now() >>> dt2 = dt1 + td(minutes=5) >>> is_same_datetime(dt1, dt2) False >>> is_same_datetime(dt1, dt2, tol=td(minutes=2)) False >>> is_same_datetime(dt1, dt2, tol=td(minutes=5)) True
- bubop.time.parse_datetime(s: str) datetime
Parse a datetime from the given string.
Usage:
>>> parse_datetime("2019-03-05") == datetime.datetime(2019, 3, 5, 0, 0) True >>> is_same_datetime(parse_datetime("2019-03-05T00:03:09Z"), datetime.datetime(2019, 3, 5, 0, 3, 9, tzinfo=dateutil.tz.tzutc())) True >>> is_same_datetime(parse_datetime("2019-03-05T00:03:01.1234Z"), datetime.datetime(2019, 3, 5, 0, 3, 1, 123400, tzinfo=dateutil.tz.tzutc())) True >>> is_same_datetime(parse_datetime("2019-03-08T00:29:06.602Z"), datetime.datetime(2019, 3, 8, 0, 29, 6, 602000, tzinfo=dateutil.tz.tzutc())) True
Module contents
Init.
- exception bubop.AuthenticationError(appname: str)
Bases:
BaseExceptionException raised when authentication with a certain application/service failed
- exception bubop.CliIncompatibleOptionsError(opt1: Any, opt2: Any)
Bases:
BaseExceptionException raised when incompatible options are given in the CLI of a program.
Usage:
>>> raise CliIncompatibleOptionsError("foo", "bar") Traceback (most recent call last): bubop.exceptions.CliIncompatibleOptionsError: Provided option groups foo and bar are incompatible with each other
- class bubop.CommonDir
Bases:
objectGet the path to one of the standard user directories - depending on the OS at hand.
- static cache(*args, **kargs)
- static config(*args, **kargs)
- class bubop.ExitHooks(print_fn=<built-in function print>)
Bases:
objectMonkeypatch sys.exit + set the excepthook to figure out when an exception or an exit event was raised.
Set this during program execution and then, e.g., during program teardown, e.g., using atexit, figure out whether an exception was raised or whether the program exited successfully or failed.
- exc_handler(exc_type, exc_value, tb, *args)
Exception handler override.
- exit(code=0)
Exit function override.
- register()
Register the exit hook.
- class bubop.FileType(*values)
Bases:
EnumEnum to represent an entity on a filesystem and abstract operations on them.
>>> ft = FileType.FILE >>> ft.exists(Path("/etc/passwd")) True >>> ft.exists(Path("/etc/")) False
>>> ft = FileType.DIR >>> ft.exists(Path("/etc/passwd")) False >>> ft.exists(Path("/etc/")) True
- DIR = 2
- FILE = 1
- FILE_OR_DIR = 3
- exists(path: Path) bool
True if the give npath exists. Uses the appropriate function for the Filepath at hand.
- exception bubop.NoSuchFileOrDirectoryError(name)
Bases:
BaseExceptionException raised when file/directory is not found.
Usage:
>>> raise NoSuchFileOrDirectoryError("foo") Traceback (most recent call last): bubop.exceptions.NoSuchFileOrDirectoryError: No such file or directory -> foo
- exception bubop.NotEnoughArgumentsError
Bases:
BaseExceptionException raised when incompatible options are given in the CLI of a program.
Usage:
>>> raise NotEnoughArgumentsError() Traceback (most recent call last): bubop.exceptions.NotEnoughArgumentsError: ...
- exception bubop.OperatingSystemNotSupportedError(os_name: str)
Bases:
BaseExceptionException raised when an operation is not supported for the OS at hand.
Usage:
>>> raise OperatingSystemNotSupportedError("Windows") Traceback (most recent call last): bubop.exceptions.OperatingSystemNotSupportedError: Operation is not supported for this OS -> Windows
- class bubop.PrefsManager(app_name: str, config_fname: str = 'cfg.yaml', logger=<loguru.logger handlers=[(id=0, level=10, sink=<stderr>)]>)
Bases:
objectManage application-related preferences.
All the preferences of the app are stored in a key-value store (aka dict). You can either access this dict via the .contents property or the PrefsManager instance itself using the same methods as a standard dict (
key in prefs_managerorprefs_manager["key"]) or using them as attributes: (prefs_manager.key)- property config_directory: Path
Get the path to the top-level config directory of the preferences at hand.
- property config_file: Path
Get the path to the config file of the preferences at hand.
- empty() bool
Returns whether the current preferences store is empty.
- flush_config(p: Path)
Helper class for writing the current cached settings to a file.
- Parameters:
p – Path to write the current settings. The given file is to be overwritten
- items()
Return the items in the Preferences Manager - similar to a dict.
- keys() Sequence[Any]
Return the list of keys in the Preferences Manager
- update_latest(new_val)
Update the latest fetched setting.
- values()
Return the list of values in the Preferences Manager
- bubop.add_bool_argument(parser: ArgumentParser, arg_name: str, default: bool | None = None, true_help: str | None = None)
Add a boolean CLI argument to the given ArgumentParser object.
The flag defaults to False if no other is specified
Usage:
>>> import argparse >>> parser = argparse.ArgumentParser(description="SomeArgumentParser") >>> add_bool_argument(parser, "someflag") >>> add_bool_argument(parser, "someflag2", default=True) >>> add_bool_argument(parser, "someflag3", default=False) >>> add_bool_argument(parser, "someflag4", true_help="somehelp4") >>> add_bool_argument(parser, "a_flag") >>> add_bool_argument(parser, "b-flag") >>> config = parser.parse_args(["--someflag"]) # basic >>> config.someflag True >>> config = parser.parse_args(["--no-someflag"]) >>> config.someflag False >>> config = vars(parser.parse_args([])) # defaults >>> config["someflag"] == False True >>> config["someflag2"] == True True >>> config["someflag3"] == False True >>> config["someflag4"] == False True >>> "somehelp4" in parser.format_help() True >>> parser.parse_args(["--someflag", "--no-someflag"]) # exception Traceback (most recent call last): ... SystemExit: 2 >>> config = vars(parser.parse_args(["--a_flag"])) >>> config["a_flag"] == True True >>> config = vars(parser.parse_args(["--b-flag"])) >>> config["b-flag"] == True True
- bubop.all_subclasses(cls: type[Any]) set[type[Any]]
Recursively get all the (reachable) subclasses of the given class.
Usage:
>>> class Foo: pass >>> class Bar(Foo): pass >>> class Baz(Foo): pass >>> class Bing(Bar): pass >>> sorted([c.__name__ for c in all_subclasses(Foo)]) ['Bar', 'Baz', 'Bing']
- bubop.assume_local_tz_if_none(dt: datetime) datetime
If there is no timezone in the given datetime object, assign a local timezone.
In all cases return a new instance of the datetime object.
Usage:
>>> dt = datetime.datetime(2019, 3, 8, 0, 29, 6) >>> dt.tzinfo is None True >>> dt = assume_local_tz_if_none(dt) >>> dt.tzinfo is None False >>> dt_old = datetime.datetime.now(tz=dateutil.tz.tzlocal()) >>> dt_old.tzinfo is not None True >>> dt = assume_local_tz_if_none(dt_old) >>> dt.tzinfo is None False
- bubop.camel_case_to_dashed(s: str) str
Convert a CamelCase string into the dashed representation.
>>> camel_case_to_dashed("KalimeraKalinuxta") 'kalimera-kalinuxta' >>> camel_case_to_dashed("somethingIsRotten") 'something-is-rotten' >>> camel_case_to_dashed("SLAM") 'slam'
- bubop.check_optional_mutually_exclusive(arg1: Any, arg2: Any) None
Check if the given mutually exclusive args indeed hold the said required rule (optional + mutual exclusivity)
Raise a CliIncompatibleOptionsError if they don’t uphold the rule.
>>> kalimera = 1 >>> kalinuxta = 2 >>> check_optional_mutually_exclusive(kalimera, kalinuxta) Traceback (most recent call last): bubop.exceptions.CliIncompatibleOptionsError: ... kalimera ... kalinuxta ... >>> kalimera = None >>> check_optional_mutually_exclusive(kalimera, kalinuxta) == None True >>> kalinuxta = None >>> check_optional_mutually_exclusive(kalimera, kalinuxta) == None True
- bubop.check_required_mutually_exclusive(arg1: Any, arg2: Any, arg1_name: str, arg2_name: str) None
Check if the given mutually exclusive args indeed hold the said required rule (required + mutual exclusivity)
Raise exception if they don’t uphold the rule.
- bubop.format_datetime_tz(dt: datetime) str
Format a datetime object according to the ISO specifications containing the ‘T’ and ‘Z’ separators
Usage:
>>> format_datetime_tz(datetime.datetime(2019, 3, 5, 0, 3, 9, 1234)) '2019-03-05T00:03:09.001234Z' >>> format_datetime_tz(datetime.datetime(2019, 3, 5, 0, 3, 9, 123)) '2019-03-05T00:03:09.000123Z'
- bubop.format_dict(items: Mapping[Any, Any], align_items: bool = True, **kargs) str
Utility for formatting a dictionary - similar to print.pformat.
Accepts mostly the same arguments as format_list.
- bubop.format_list(items: Sequence[str], header: str, indent=2, bullet_char='-', header_sep='=', prefix: str = '', suffix: str = '') str
Format and return a string with the corresponding header and all the items each occupying a single line and with the specified indentation.
- bubop.get_object_unique_name(obj: Any) str
Return a unique string associated with the given object.
That string is constructed as follows: <object class name>_<object_hex_id>
- bubop.get_random_string(len_=10) str
Return a random string containing ascii characters, digits and punctuation marks.
- bubop.get_valid_filename(s: str) str
Return a filename-compatible version of the given string s.
- Parameters:
s – String to be used as the base of the filename. You may also pass non-string objects that will however be able to convert to strings via the str operator.
>>> get_valid_filename(r"5678^()^") '5678____' >>> get_valid_filename(r"a|string\go/es||here") 'a_string_go_es__here' >>> get_valid_filename(r"strin***g") 'strin___g'
See also
- bubop.inspect_var_name(var: Any, level=2) str | None
Retrieve the name of the variable var passed from the caller to this function.
Use the level argument to refer to the argument name of the caller’s caller (level=2) or the caller’s caller’s caller, (level=3) etc. instead.
Quite experimental function in nature, may not work as expected.
Usage:
>>> var1 = "kalimera" >>> inspect_var_name(var1, level=1) 'var1' >>> fn = lambda x: (inspect_var_name(x, level=1), inspect_var_name(x)) >>> fn(var1) ('x', 'var1') >>> inspect_var_name(var1, level=1000) == None Traceback (most recent call last): bubop.exceptions.TooShallowStackError: Stack has less ... >>> inspect_var_name(1, level=1) == None True
- bubop.is_same_datetime(dt1: datetime, dt2: datetime, tol: timedelta = datetime.timedelta(0)) bool
Compare two datetime.datetime objects.
If the timezone is empty, assume local timezone.
Usage:
>>> dt = datetime.datetime >>> td = datetime.timedelta >>> dt1 = datetime.datetime.now() >>> dt2 = dt1 + td(minutes=5) >>> is_same_datetime(dt1, dt2) False >>> is_same_datetime(dt1, dt2, tol=td(minutes=2)) False >>> is_same_datetime(dt1, dt2, tol=td(minutes=5)) True
- bubop.log_to_syslog(name: str, level: Literal['FATAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'TRACE'] = 'WARNING')
Enable logging to syslog for the given logger.
This method does not remove any of the existing logging handlers.
- bubop.loguru_set_verbosity(verbosity: int)
Set the verbosity of the tqdm logger.
- Parameters:
verbosity – 0 for >= INFO, 1 for >= DEBUG, 2 for >= TRACE
- bubop.loguru_tqdm_sink(verbosity: int)
Change the default loguru logger to use tqdm.
- Parameters:
verbosity – Set the verbosity of the tqdm logger. 0 for >= INFO, 1 for >= DEBUG, 2 for >= TRACE
- bubop.non_empty(title: str, value: str, join_with: str = ' -> ', newline=True) str
Return a one-line formatted string of “title -> value” but only if value is a non-empty string. Otherwise return an empty string
>>> non_empty(title="title", value="value") 'title -> value\n' >>> non_empty(title="title", value=None) ''
- bubop.parse_datetime(s: str) datetime
Parse a datetime from the given string.
Usage:
>>> parse_datetime("2019-03-05") == datetime.datetime(2019, 3, 5, 0, 0) True >>> is_same_datetime(parse_datetime("2019-03-05T00:03:09Z"), datetime.datetime(2019, 3, 5, 0, 3, 9, tzinfo=dateutil.tz.tzutc())) True >>> is_same_datetime(parse_datetime("2019-03-05T00:03:01.1234Z"), datetime.datetime(2019, 3, 5, 0, 3, 1, 123400, tzinfo=dateutil.tz.tzutc())) True >>> is_same_datetime(parse_datetime("2019-03-08T00:29:06.602Z"), datetime.datetime(2019, 3, 8, 0, 29, 6, 602000, tzinfo=dateutil.tz.tzutc())) True
- bubop.pickle_dump(item: Any, path: Path | str, *, protocol=0, **kargs)
Helper method to serialize your dictionary to the given path.
By default use protocol 0.
- bubop.pickle_load(path: Path | str) Any
Pickle-load using the given path.
- bubop.read_gpg_token(p: Path, timeout_secs: int = 3) str
Read the token from a gpg file.
Raise a RuntimeError if the decryption was unsuccessful.
- bubop.valid_dir(s: str) Path
Return a pathlib.Path from the given string.
If the input does not correspond to a valid directory, then raise an exception
>>> valid_dir("/etc/") PosixPath... >>> valid_dir("/etc/passwd") Traceback (most recent call last): NotADirectoryError: ...
- bubop.valid_file(s: str) Path
Return a pathlib.Path from the given string.
If the input does not correspond to a valid directory, then raise an exception >>> valid_file(“/etc/”) Traceback (most recent call last): FileNotFoundError: … >>> valid_file(“/etc/passwd”) PosixPath…
- bubop.valid_path(s: str, filetype=FileType.FILE_OR_DIR) Path
Return a pathlib.Path from the given string.
If the input does not correspond to a valid path, then raise an exception
>>> valid_path("/etc") PosixPath... >>> valid_path("/etc/some-invalid-path") Traceback (most recent call last): bubop.exceptions.NoSuchFileOrDirectoryError: No such ...
>>> valid_path("/etc", filetype=FileType.FILE) Traceback (most recent call last): FileNotFoundError: ...
>>> valid_path("/etc/passwd", filetype=FileType.FILE) PosixPath...
>>> valid_path("/etc/passwd", filetype=FileType.DIR) Traceback (most recent call last): NotADirectoryError: ... >>> valid_path("/etc", filetype=FileType.DIR) PosixPath...
- bubop.verbosity_int_to_std_logging_lvl(verbosity: int) int
Map an integer to a corresponding python std logging module level :param verbosity: Set the verbosity of the tqdm logger.
0 for >= INFO, 1 for >= DEBUG,
>>> verbosity_int_to_std_logging_lvl(0) 20 >>> verbosity_int_to_std_logging_lvl(1) 10 >>> verbosity_int_to_std_logging_lvl(2) 10 >>> verbosity_int_to_std_logging_lvl(3) 10 >>> verbosity_int_to_std_logging_lvl(-1) Traceback (most recent call last): RuntimeError: ...
- bubop.verbosity_int_to_str(verbosity: int) Literal['FATAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'TRACE']
Map a verbosity integer to the corresponding Loguru Level. :param verbosity: = 0 -> INFO,
= 1 -> DEBUG, >=2 -> TRACE
Usage:
>>> verbosity_int_to_str(1) 'DEBUG' >>> verbosity_int_to_str(2) 'TRACE' >>> verbosity_int_to_str(3) 'TRACE' >>> verbosity_int_to_str(-1) Traceback (most recent call last): RuntimeError: ...
- bubop.write_gpg_token(p: Path, token: str, recipient: str) None
Write the given token to a gpg file designated by p.
Raise a RuntimeError if the encryption was unsuccessful.
- bubop.xor(*args) bool
True if exactly one of the arguments of the iterable is True.
>>> xor(0,1,0,) True >>> xor(1,2,3,) False >>> xor(False, False, False) False >>> xor("kalimera", "kalinuxta") False >>> xor("", "a", "") True >>> xor("", "", "") False