From 2a98707bf8f27450e1aae3a7320e39e7a060409f Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Tue, 11 Jul 2023 20:27:52 +0100 Subject: [PATCH] Adds ability to extend one config with another apply_config() checks for 'extends' in TOML config 2.3.0 section added to CHANGELOG three example extender.toml configs added minor version bump --- CHANGELOG.md | 6 ++++++ README.md | 29 +++++++++++++++++++++++++---- configs/banana/extender.toml | 12 ++++++++++++ configs/basic/extender.toml | 12 ++++++++++++ configs/potato/extender.toml | 12 ++++++++++++ pyproject.toml | 2 +- vban_cmd/vbancmd.py | 30 +++++++++++++++++++----------- 7 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 configs/banana/extender.toml create mode 100644 configs/basic/extender.toml create mode 100644 configs/potato/extender.toml diff --git a/CHANGELOG.md b/CHANGELOG.md index cb09638..3ad74ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ Before any major/minor/patch bump all unit tests will be run to verify they pass - [x] +## [2.2.0] - 2023-07-11 + +### Added + +- user configs may now extend other user configs. check `config extends` section in README. + ## [2.1.2] - 2023-07-05 ### Added diff --git a/README.md b/README.md index a804984..938bcfd 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ port = 6980 streamname = "Command1" ``` -It should be placed next to your `__main__.py` file. +It should be placed in \ / "Documents" / "Voicemeeter" / "configs" Alternatively you may pass `ip`, `port`, `streamname` as keyword arguments. @@ -359,8 +359,8 @@ vban.apply( Or for each class you may do: ```python -vban.strip[0].apply(mute: true, gain: 3.2, A1: true) -vban.bus[0].apply(A1: true) +vban.strip[0].apply({"mute": True, "gain": 3.2, "A1": True}) +vban.vban.outstream[0].apply({"on": True, "name": "streamname", "bit": 24}) ``` ## Config Files @@ -369,7 +369,7 @@ vban.bus[0].apply(A1: true) You may load config files in TOML format. Three example configs have been included with the package. Remember to save -current settings before loading a user config. To set one you may do: +current settings before loading a user config. To load one you may do: ```python import vban_cmd @@ -379,6 +379,27 @@ with vban_cmd.api('banana') as vban: will load a config file at configs/banana/example.toml for Voicemeeter Banana. +Your configs may be located in one of the following paths: +- \ / "configs" / kind_id +- \ / ".config" / "vban-cmd" / kind_id +- \ / "Documents" / "Voicemeeter" / "configs" / kind_id + +If a config with the same name is located in multiple locations, only the first one found is loaded into memory, in the above order. + +#### `config extends` + +You may also load a config that extends another config with overrides or additional parameters. + +You just need to define a key `extends` in the config TOML, that names the config to be extended. + +Three example 'extender' configs are included with the repo. You may load them with: + +```python +import voicemeeterlib +with voicemeeterlib.api('banana') as vm: + vm.apply_config('extender') +``` + ## Events Level updates are considered high volume, by default they are NOT listened for. Use `subs` keyword arg to initialize event updates. diff --git a/configs/banana/extender.toml b/configs/banana/extender.toml new file mode 100644 index 0000000..6383eb9 --- /dev/null +++ b/configs/banana/extender.toml @@ -0,0 +1,12 @@ +extends = "example" +[strip-0] +label = "strip0_extended" +A1 = false +gain = 0.0 + +[bus-0] +label = "bus0_extended" +mute = false + +[vban-in-3] +name = "vban_extended" diff --git a/configs/basic/extender.toml b/configs/basic/extender.toml new file mode 100644 index 0000000..6383eb9 --- /dev/null +++ b/configs/basic/extender.toml @@ -0,0 +1,12 @@ +extends = "example" +[strip-0] +label = "strip0_extended" +A1 = false +gain = 0.0 + +[bus-0] +label = "bus0_extended" +mute = false + +[vban-in-3] +name = "vban_extended" diff --git a/configs/potato/extender.toml b/configs/potato/extender.toml new file mode 100644 index 0000000..6383eb9 --- /dev/null +++ b/configs/potato/extender.toml @@ -0,0 +1,12 @@ +extends = "example" +[strip-0] +label = "strip0_extended" +A1 = false +gain = 0.0 + +[bus-0] +label = "bus0_extended" +mute = false + +[vban-in-3] +name = "vban_extended" diff --git a/pyproject.toml b/pyproject.toml index e7d5011..981b1cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "vban-cmd" -version = "2.2.0" +version = "2.3.0" description = "Python interface for the VBAN RT Packet Service (Sendtext)" authors = ["onyx-and-iris "] license = "MIT" diff --git a/vban_cmd/vbancmd.py b/vban_cmd/vbancmd.py index b2589aa..8f79b64 100644 --- a/vban_cmd/vbancmd.py +++ b/vban_cmd/vbancmd.py @@ -64,8 +64,9 @@ class VbanCmd(metaclass=ABCMeta): def get_filepath(): filepaths = [ Path.cwd() / "vban.toml", + Path.cwd() / "configs" / "vban.toml", Path.home() / ".config" / "vban-cmd" / "vban.toml", - Path.home() / "Documents" / "Voicemeeter" / "vban.toml", + Path.home() / "Documents" / "Voicemeeter" / "configs" / "vban.toml", ] for filepath in filepaths: if filepath.exists(): @@ -75,11 +76,10 @@ class VbanCmd(metaclass=ABCMeta): with open(filepath, "rb") as f: conn = tomllib.load(f) assert ( - "ip" in conn["connection"] - ), "please provide ip, by kwarg or config" + "connection" in conn and "ip" in conn["connection"] + ), "expected [connection][ip] in vban config" return conn["connection"] - else: - raise VBANCMDError("no ip provided and no vban.toml located.") + raise VBANCMDError("no ip provided and no vban.toml located.") def __enter__(self): self.login() @@ -101,7 +101,7 @@ class VbanCmd(metaclass=ABCMeta): self.producer.start() self.logger.info( - "Successfully logged into {kind} with ip='{ip}', port={port}, streamname='{streamname}'".format( + "Successfully logged into VBANCMD {kind} with ip='{ip}', port={port}, streamname='{streamname}'".format( **self.__dict__ ) ) @@ -189,16 +189,24 @@ class VbanCmd(metaclass=ABCMeta): def apply_config(self, name): """applies a config from memory""" - error_msg = ( + ERR_MSG = ( f"No config with name '{name}' is loaded into memory", f"Known configs: {list(self.configs.keys())}", ) try: - self.apply(self.configs[name]) - self.logger.info(f"Profile '{name}' applied!") + config = self.configs[name].copy() except KeyError as e: - self.logger.error(("\n").join(error_msg)) - raise VBANCMDError(("\n").join(error_msg)) from e + self.logger.error(("\n").join(ERR_MSG)) + raise VBANCMDError(("\n").join(ERR_MSG)) from e + + if "extends" in config: + extended = config.pop("extends") + config = self.configs[extended] | config + self.logger.debug( + f"profile '{name}' extends '{extended}', profiles merged.." + ) + self.apply(config) + self.logger.info(f"Profile '{name}' applied!") def logout(self): self.running = False