Skip to content

Instantly share code, notes, and snippets.

@outofmbufs
Last active December 15, 2020 14:44
Show Gist options
  • Save outofmbufs/1c893f2759b269984cd20247ee672e7b to your computer and use it in GitHub Desktop.
Save outofmbufs/1c893f2759b269984cd20247ee672e7b to your computer and use it in GitHub Desktop.
Python argparse helper for parsing comma-separated options and other list-like parameters. Enables things like "--blah 17,42"
# Python support for argument parsing of list-like things (usually comma separated).
# For example:
# def commapair(s):
# return argtuple(s, n=2)
# can then be used as:
# type=commapair
# in argparse for arguments like "--blah 17,42"
#
def argtuple(s, *dflts, n=None, seps=(',',), type=int):
"""Return tuple of 'type' from a,b,c,d... format.
Raises ValueError if s cannot be parsed or converted (per type())
seps: separators. Each is tried, in order, stopping when s.split()
results in multiple fields or once all have been tried.
Default is comma.
type: conversion function to apply to each string from s.split()
n: enforced tuple length. Interacts with dflts. If n is None and
no dflts are given, the resulting length is "whatever"
dflts: default values for unspecified fields. If n is None, it is
determined by len(dflts). If n > 1 and len(dflts) == 1 then that
single default value will be used for all fields.
"""
if len(dflts) > 0:
if n is None:
n = len(dflts)
if n > 1:
if len(dflts) == 1:
dflts = [dflts[0]] * n
elif len(dflts) != n:
raise ValueError(f"n is {n} but len(dflts) is {len(dflts)}")
if s:
for sep in seps:
a = s.split(sep)
if len(a) > 1:
break
else:
a = []
if n is not None:
alen = len(a)
if alen > n:
raise ValueError(f"too many fields in {s}")
if alen < n:
if len(dflts) == 0:
raise ValueError(f"too few fields in {s}")
a += dflts[alen:]
return tuple(map(type, a))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment