mirror of
https://github.com/onyx-and-iris/vban-cli.git
synced 2026-03-02 21:19:11 +00:00
initial commit
CLI skeletal structure implemented --version flag implemented configuration via flag+env vars implemented strip command group implemented + some subcommands custom help formatter implemented.
This commit is contained in:
commit
44fdeda6e4
222
.gitignore
vendored
Normal file
222
.gitignore
vendored
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
# Python-generated files
|
||||||
|
__pycache__/
|
||||||
|
*.py[oc]
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
wheels/
|
||||||
|
*.egg-info
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.venv
|
||||||
|
# Generated by ignr: github.com/onyx-and-iris/ignr
|
||||||
|
|
||||||
|
## Python ##
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[codz]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# UV
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
#uv.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
#poetry.toml
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
||||||
|
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
||||||
|
#pdm.lock
|
||||||
|
#pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# pixi
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
||||||
|
#pixi.lock
|
||||||
|
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
||||||
|
# in the .venv directory. It is recommended not to include this directory in version control.
|
||||||
|
.pixi
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.envrc
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# Abstra
|
||||||
|
# Abstra is an AI-powered process automation framework.
|
||||||
|
# Ignore directories containing user credentials, local state, and settings.
|
||||||
|
# Learn more at https://abstra.io/docs
|
||||||
|
.abstra/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||||
|
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||||
|
# you could uncomment the following to ignore the entire vscode folder
|
||||||
|
# .vscode/
|
||||||
|
|
||||||
|
# Ruff stuff:
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# PyPI configuration file
|
||||||
|
.pypirc
|
||||||
|
|
||||||
|
# Cursor
|
||||||
|
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
||||||
|
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
||||||
|
# refer to https://docs.cursor.com/context/ignore-files
|
||||||
|
.cursorignore
|
||||||
|
.cursorindexingignore
|
||||||
|
|
||||||
|
# Marimo
|
||||||
|
marimo/_static/
|
||||||
|
marimo/_lsp/
|
||||||
|
__marimo__/
|
||||||
|
|
||||||
|
# End of ignr
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Onyx and Iris
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
56
README.md
Normal file
56
README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# vmr-cli
|
||||||
|
|
||||||
|
[](https://github.com/astral-sh/uv)
|
||||||
|
[](https://github.com/astral-sh/ruff)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
#### With uv
|
||||||
|
|
||||||
|
```console
|
||||||
|
uv tool install vmr-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
#### With pipx
|
||||||
|
|
||||||
|
```console
|
||||||
|
pipx install vmr-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
The CLI should now be discoverable as `vmr-cli`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Flags
|
||||||
|
|
||||||
|
```console
|
||||||
|
vmr-cli --host=localhost --port=6980 --streamname=Command1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
example .envrc:
|
||||||
|
|
||||||
|
```env
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
export VMR_CLI_HOST="localhost"
|
||||||
|
export VMR_CLI_PORT=6980
|
||||||
|
export VMR_CLI_STREAMNAME=Command1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Use
|
||||||
|
|
||||||
|
*To be completed*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
`vmr-cli` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
||||||
27
pyproject.toml
Normal file
27
pyproject.toml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
[project]
|
||||||
|
name = "vmr-cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
license = { text = "LICENSE" }
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
dependencies = ["cyclopts>=4.6.0", "vban-cmd>=2.5.2"]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 4 - Alpha",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
vmr-cli = "vmr_cli.app:run"
|
||||||
|
|
||||||
|
[tool.uv]
|
||||||
|
package = true
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
vban-cmd = { path = "../vban-cmd-python" }
|
||||||
77
ruff.toml
Normal file
77
ruff.toml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# Exclude a variety of commonly ignored directories.
|
||||||
|
exclude = [
|
||||||
|
".bzr",
|
||||||
|
".direnv",
|
||||||
|
".eggs",
|
||||||
|
".git",
|
||||||
|
".git-rewrite",
|
||||||
|
".hg",
|
||||||
|
".ipynb_checkpoints",
|
||||||
|
".mypy_cache",
|
||||||
|
".nox",
|
||||||
|
".pants.d",
|
||||||
|
".pyenv",
|
||||||
|
".pytest_cache",
|
||||||
|
".pytype",
|
||||||
|
".ruff_cache",
|
||||||
|
".svn",
|
||||||
|
".tox",
|
||||||
|
".venv",
|
||||||
|
".vscode",
|
||||||
|
"__pypackages__",
|
||||||
|
"_build",
|
||||||
|
"buck-out",
|
||||||
|
"build",
|
||||||
|
"dist",
|
||||||
|
"node_modules",
|
||||||
|
"site-packages",
|
||||||
|
"venv",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Same as Black.
|
||||||
|
line-length = 88
|
||||||
|
indent-width = 4
|
||||||
|
|
||||||
|
# Assume Python 3.10
|
||||||
|
target-version = "py310"
|
||||||
|
|
||||||
|
[lint]
|
||||||
|
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
||||||
|
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
|
||||||
|
# McCabe complexity (`C901`) by default.
|
||||||
|
select = ["E4", "E7", "E9", "F"]
|
||||||
|
ignore = []
|
||||||
|
|
||||||
|
# Allow fix for all enabled rules (when `--fix`) is provided.
|
||||||
|
fixable = ["ALL"]
|
||||||
|
unfixable = []
|
||||||
|
|
||||||
|
# Allow unused variables when underscore-prefixed.
|
||||||
|
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||||
|
|
||||||
|
[format]
|
||||||
|
# Unlike Black, use single quotes for strings.
|
||||||
|
quote-style = "single"
|
||||||
|
|
||||||
|
# Like Black, indent with spaces, rather than tabs.
|
||||||
|
indent-style = "space"
|
||||||
|
|
||||||
|
# Like Black, respect magic trailing commas.
|
||||||
|
skip-magic-trailing-comma = false
|
||||||
|
|
||||||
|
# Like Black, automatically detect the appropriate line ending.
|
||||||
|
line-ending = "auto"
|
||||||
|
|
||||||
|
# Enable auto-formatting of code examples in docstrings. Markdown,
|
||||||
|
# reStructuredText code/literal blocks and doctests are all supported.
|
||||||
|
#
|
||||||
|
# This is currently disabled by default, but it is planned for this
|
||||||
|
# to be opt-out in the future.
|
||||||
|
docstring-code-format = false
|
||||||
|
|
||||||
|
# Set the line length limit used when formatting code snippets in
|
||||||
|
# docstrings.
|
||||||
|
#
|
||||||
|
# This only has an effect when the `docstring-code-format` setting is
|
||||||
|
# enabled.
|
||||||
|
docstring-code-line-length = "dynamic"
|
||||||
3
src/vmr_cli/__init__.py
Normal file
3
src/vmr_cli/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from importlib.metadata import version
|
||||||
|
|
||||||
|
__version__ = version('vmr-cli')
|
||||||
52
src/vmr_cli/app.py
Normal file
52
src/vmr_cli/app.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
import vban_cmd
|
||||||
|
from cyclopts import App, Parameter, config
|
||||||
|
|
||||||
|
from . import __version__ as version
|
||||||
|
from . import console, strip
|
||||||
|
from .context import Context
|
||||||
|
|
||||||
|
app = App(
|
||||||
|
config=config.Env(
|
||||||
|
'VMR_CLI_',
|
||||||
|
), # Environment variable prefix for configuration parameters
|
||||||
|
version=version,
|
||||||
|
)
|
||||||
|
app.command(strip.app.meta, name='strip')
|
||||||
|
|
||||||
|
|
||||||
|
@Parameter(name='*')
|
||||||
|
@dataclass
|
||||||
|
class VBANConfig:
|
||||||
|
kind: Annotated[str, Parameter(help='Kind of Voicemeeter')] = 'potato'
|
||||||
|
host: Annotated[str, Parameter(help='VBAN host')] = 'localhost'
|
||||||
|
port: Annotated[int, Parameter(help='VBAN port')] = 6980
|
||||||
|
streamname: Annotated[str, Parameter(help='VBAN stream name')] = 'Command1'
|
||||||
|
|
||||||
|
|
||||||
|
@app.meta.default
|
||||||
|
def launcher(
|
||||||
|
*tokens: Annotated[str, Parameter(show=False, allow_leading_hyphen=True)],
|
||||||
|
vban_config: Annotated[VBANConfig, Parameter()] = VBANConfig(),
|
||||||
|
):
|
||||||
|
with vban_cmd.api(
|
||||||
|
vban_config.kind,
|
||||||
|
ip=vban_config.host,
|
||||||
|
port=vban_config.port,
|
||||||
|
streamname=vban_config.streamname,
|
||||||
|
) as client:
|
||||||
|
additional_kwargs = {}
|
||||||
|
command, bound, _ = app.parse_args(tokens)
|
||||||
|
additional_kwargs['ctx'] = Context(client=client)
|
||||||
|
|
||||||
|
return command(*bound.args, **bound.kwargs, **additional_kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
try:
|
||||||
|
app.meta()
|
||||||
|
except Exception as e:
|
||||||
|
console.err.print(f'Error: {e}')
|
||||||
|
return e.code
|
||||||
4
src/vmr_cli/console.py
Normal file
4
src/vmr_cli/console.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from rich.console import Console
|
||||||
|
|
||||||
|
out = Console()
|
||||||
|
err = Console(stderr=True)
|
||||||
8
src/vmr_cli/context.py
Normal file
8
src/vmr_cli/context.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from vban_cmd.vbancmd import VbanCmd
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Context:
|
||||||
|
client: VbanCmd
|
||||||
43
src/vmr_cli/help.py
Normal file
43
src/vmr_cli/help.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from cyclopts.help import DefaultFormatter, HelpPanel
|
||||||
|
from rich.console import Console, ConsoleOptions
|
||||||
|
|
||||||
|
|
||||||
|
class CustomHelpFormatter(DefaultFormatter):
|
||||||
|
"""Custom help formatter that injects an index argument into the usage line and filters it out from the parameters list.
|
||||||
|
|
||||||
|
This formatter modifies the usage line to include an <index> argument after the 'strip' command,
|
||||||
|
and filters out any parameters related to 'index' from the Parameters section of the help output.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def render_usage(self, console: Console, options: ConsoleOptions, usage) -> None:
|
||||||
|
"""Render the usage line with index argument injected."""
|
||||||
|
if usage:
|
||||||
|
modified_usage = re.sub(
|
||||||
|
r'(\S+\s+strip)\s+(COMMAND)', r'\1 <index> \2', str(usage)
|
||||||
|
)
|
||||||
|
console.print(f'[bold]Usage:[/bold] {modified_usage}')
|
||||||
|
|
||||||
|
def __call__(
|
||||||
|
self, console: Console, options: ConsoleOptions, panel: HelpPanel
|
||||||
|
) -> None:
|
||||||
|
"""Render a help panel, filtering out the index parameter from Parameters sections."""
|
||||||
|
if panel.title == 'Parameters':
|
||||||
|
filtered_entries = [
|
||||||
|
entry
|
||||||
|
for entry in panel.entries
|
||||||
|
if not (
|
||||||
|
entry.names and any('index' in name.lower() for name in entry.names)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
filtered_panel = HelpPanel(
|
||||||
|
title=panel.title,
|
||||||
|
entries=filtered_entries,
|
||||||
|
description=panel.description,
|
||||||
|
format=panel.format,
|
||||||
|
)
|
||||||
|
super().__call__(console, options, filtered_panel)
|
||||||
|
else:
|
||||||
|
super().__call__(console, options, panel)
|
||||||
266
src/vmr_cli/strip.py
Normal file
266
src/vmr_cli/strip.py
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
from typing import Annotated, Optional
|
||||||
|
|
||||||
|
from cyclopts import App, Argument, Parameter
|
||||||
|
|
||||||
|
from . import console
|
||||||
|
from .context import Context
|
||||||
|
from .help import CustomHelpFormatter
|
||||||
|
|
||||||
|
app = App(name='strip', help_formatter=CustomHelpFormatter())
|
||||||
|
|
||||||
|
|
||||||
|
@app.meta.default
|
||||||
|
def launcher(
|
||||||
|
index: Annotated[int, Argument()] = None,
|
||||||
|
*tokens: Annotated[str, Parameter(show=False, allow_leading_hyphen=True)],
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Control the strip parameters."""
|
||||||
|
additional_kwargs = {}
|
||||||
|
command, bound, _ = app.parse_args(tokens)
|
||||||
|
if index is not None:
|
||||||
|
additional_kwargs['index'] = index
|
||||||
|
if ctx is not None:
|
||||||
|
additional_kwargs['ctx'] = ctx
|
||||||
|
|
||||||
|
return command(*bound.args, **bound.kwargs, **additional_kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='mono')
|
||||||
|
def mono(
|
||||||
|
new_state: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the mono state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_state : bool, optional
|
||||||
|
If provided, sets the mono state to this value. If not provided, the current mono state is printed.
|
||||||
|
"""
|
||||||
|
if new_state is None:
|
||||||
|
console.out.print(ctx.client.strip[index].mono)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].mono = new_state
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='solo')
|
||||||
|
def solo(
|
||||||
|
new_state: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the solo state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_state : bool, optional
|
||||||
|
If provided, sets the solo state to this value. If not provided, the current solo state is printed.
|
||||||
|
"""
|
||||||
|
if new_state is None:
|
||||||
|
console.out.print(ctx.client.strip[index].solo)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].solo = new_state
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='mute')
|
||||||
|
def mute(
|
||||||
|
new_state: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the mute state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_state : bool, optional
|
||||||
|
If provided, sets the mute state to this value. If not provided, the current mute state is printed.
|
||||||
|
"""
|
||||||
|
if new_state is None:
|
||||||
|
console.out.print(ctx.client.strip[index].mute)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].mute = new_state
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='gain')
|
||||||
|
def gain(
|
||||||
|
new_value: Annotated[Optional[float], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the gain of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : float, optional
|
||||||
|
If provided, sets the gain to this value. If not provided, the current gain is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].gain)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].gain = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='A1')
|
||||||
|
def a1(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the A1 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the A1 state to this value. If not provided, the current A1 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].A1)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].A1 = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='A2')
|
||||||
|
def a2(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the A2 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the A2 state to this value. If not provided, the current A2 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].A2)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].A2 = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='A3')
|
||||||
|
def a3(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the A3 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the A3 state to this value. If not provided, the current A3 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].A3)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].A3 = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='A4')
|
||||||
|
def a4(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the A4 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the A4 state to this value. If not provided, the current A4 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].A4)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].A4 = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='A5')
|
||||||
|
def a5(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the A5 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the A5 state to this value. If not provided, the current A5 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].A5)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].A5 = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='B1')
|
||||||
|
def b1(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the B1 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the B1 state to this value. If not provided, the current B1 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].B1)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].B1 = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='B2')
|
||||||
|
def b2(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the B2 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the B2 state to this value. If not provided, the current B2 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].B2)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].B2 = new_value
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name='B3')
|
||||||
|
def b3(
|
||||||
|
new_value: Annotated[Optional[bool], Argument()] = None,
|
||||||
|
*,
|
||||||
|
index: Annotated[int, Parameter(show=False)] = None,
|
||||||
|
ctx: Annotated[Context, Parameter(show=False)] = None,
|
||||||
|
):
|
||||||
|
"""Get or set the B3 state of the specified strip.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
new_value : bool, optional
|
||||||
|
If provided, sets the B3 state to this value. If not provided, the current B3 state is printed.
|
||||||
|
"""
|
||||||
|
if new_value is None:
|
||||||
|
console.out.print(ctx.client.strip[index].B3)
|
||||||
|
return
|
||||||
|
ctx.client.strip[index].B3 = new_value
|
||||||
124
uv.lock
generated
Normal file
124
uv.lock
generated
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
version = 1
|
||||||
|
revision = 3
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "attrs"
|
||||||
|
version = "25.4.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cyclopts"
|
||||||
|
version = "4.6.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "attrs" },
|
||||||
|
{ name = "docstring-parser" },
|
||||||
|
{ name = "rich" },
|
||||||
|
{ name = "rich-rst" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/49/5c/88a4068c660a096bbe87efc5b7c190080c9e86919c36ec5f092cb08d852f/cyclopts-4.6.0.tar.gz", hash = "sha256:483c4704b953ea6da742e8de15972f405d2e748d19a848a4d61595e8e5360ee5", size = 162724, upload-time = "2026-02-23T15:44:49.286Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/eb/1e8337755a70dc7d7ff10a73dc8f20e9352c9ad6c2256ed863ac95cd3539/cyclopts-4.6.0-py3-none-any.whl", hash = "sha256:0a891cb55bfd79a3cdce024db8987b33316aba11071e5258c21ac12a640ba9f2", size = 200518, upload-time = "2026-02-23T15:44:47.854Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "docstring-parser"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "docutils"
|
||||||
|
version = "0.22.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markdown-it-py"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "mdurl" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdurl"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.19.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rich"
|
||||||
|
version = "14.3.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markdown-it-py" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rich-rst"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "docutils" },
|
||||||
|
{ name = "rich" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/13/2f/b4530fbf948867702d0a3f27de4a6aab1d156f406d72852ab902c4d04de9/rich_rst-1.3.2-py3-none-any.whl", hash = "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a", size = 12567, upload-time = "2025-10-14T16:49:42.953Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vban-cmd"
|
||||||
|
version = "2.5.2"
|
||||||
|
source = { directory = "../vban-cmd-python" }
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [{ name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=2.0.1,<3.0" }]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vmr-cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { editable = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cyclopts" },
|
||||||
|
{ name = "vban-cmd" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "cyclopts", specifier = ">=4.6.0" },
|
||||||
|
{ name = "vban-cmd", directory = "../vban-cmd-python" },
|
||||||
|
]
|
||||||
Loading…
x
Reference in New Issue
Block a user