Skip to content

Instantly share code, notes, and snippets.

@tsibley
Created December 15, 2022 00:26
Show Gist options
  • Save tsibley/3d95d090523d8fefe33b034541c1562a to your computer and use it in GitHub Desktop.
Save tsibley/3d95d090523d8fefe33b034541c1562a to your computer and use it in GitHub Desktop.
from typing import Dict, Union
from shlex import quote as shquote, split as shsplitwords
def shquotewords(s: str) -> str:
"""
Split string *s* into (POSIX) shell words, quote each word, and join them
back into a string.
This is suitable for properly quoting multi-word, user-defined values which
should follow shell quoting and escaping semantics (e.g. to allow spaces in
single words) but not allow shell features like variable interpolation,
command substition, redirection, piping, etc.
>>> shquotewords('''a "b c" d $E''')
"a 'b c' d '$E'"
>>> shquotewords('''foo >bar''')
"foo '>bar'"
"""
return " ".join(shquote(word) for word in shsplitwords(s))
def augur_options(opts: Dict[str, Union[str, list, None]]) -> str:
"""
Converts a dictionary of command-line config options to a string suitable
for use in an ``augur`` invocation.
Values are appropriately quoted/escaped:
>>> augur_options({"--min-length": 9000, "--include-where": "state = WA"})
"--min-length 9000 --include-where 'state = WA'"
Flags are keys where the value is ``None``:
>>> augur_options({"--exclude-all": None})
'--exclude-all'
Options that take multiple values can use shell-like quoting and escaping
in a single Python string:
>>> augur_options({"--metadata-id-columns": 'strain "seq name" seq\ id $id'})
"--metadata-id-columns strain 'seq name' 'seq id' '$id'"
or use a Python list:
>>> augur_options({"--metadata-id-columns": ["strain", "seq name", "seq id", "$id"]})
"--metadata-id-columns strain 'seq name' 'seq id' '$id'"
"""
return " ".join(
shquotewords(opt if val is None else f"{opt} {val}")
for opt, val in opts.items())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment