Skip to content

Instantly share code, notes, and snippets.

@mnm364
Last active April 1, 2021 16:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mnm364/edee068a5cebbfac43547b57b7c842f1 to your computer and use it in GitHub Desktop.
Save mnm364/edee068a5cebbfac43547b57b7c842f1 to your computer and use it in GitHub Desktop.
Composable Python argparse actions
import argparse
def compose_actions(*actions):
"""Compose many argparse actions into one callable action.
Args:
*actions: The actions to compose.
Returns:
argparse.Action: Composed action.
"""
class ComposableAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
for action in actions:
action(option_string, self.dest).__call__(parser,
namespace,
values,
option_string)
return ComposableAction
import argparse
import simplejson as json
import os
from composable_actions import compose_actions
class ReadableFileAction(argparse.Action):
"""Argparse hook to check for readable file within directory."""
def __call__(self, parser, namespace, values, option_string=None):
"""Readble file action callable.
Raises:
parser.error: The file is not readable.
"""
if not values:
return
prospective_file = values
prospective_dir = os.path.dirname(os.path.abspath(prospective_file))
if not os.path.isdir(prospective_dir):
raise parser.error(
'{} is not a valid file path'.format(prospective_file)
)
if os.access(prospective_dir + '/' + prospective_file, os.R_OK):
setattr(namespace, self.dest, prospective_file)
return
raise parser.error('{} isnt a readable file'.format(prospective_file))
class LoadFileToJsonAction(argparse.Action):
"""Argparse hook to read JSON file and load into Python dictionary."""
def __call__(self, parser, namespace, values, option_string=None):
"""Load file to JSON Action.
Raises:
parser.error: invalid JSON.
"""
with open(values, 'r') as file:
data = file.read()
try:
setattr(parser, self.dest, json.loads(data))
except json.scanner.JSONDecodeError:
parser.error('invalid JSON in {}'.format(values))
parser = argparse.ArgumentParser()
parser.add_argument('--json-file', dest='data', action=compose_actions(ReadableFileAction, LoadToJsonAction))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment