Initial commit
This commit is contained in:
188
skills/argparse-patterns/templates/custom-actions.py
Executable file
188
skills/argparse-patterns/templates/custom-actions.py
Executable file
@@ -0,0 +1,188 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Custom action classes for advanced argument processing.
|
||||
|
||||
Usage:
|
||||
python custom-actions.py --env-file .env
|
||||
python custom-actions.py --key API_KEY --key DB_URL
|
||||
python custom-actions.py --range 1-10 --range 20-30
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class LoadEnvFileAction(argparse.Action):
|
||||
"""Custom action to load environment variables from file."""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
env_file = Path(values)
|
||||
if not env_file.exists():
|
||||
parser.error(f"Environment file does not exist: {values}")
|
||||
|
||||
env_vars = {}
|
||||
with open(env_file, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line and not line.startswith('#'):
|
||||
if '=' in line:
|
||||
key, value = line.split('=', 1)
|
||||
env_vars[key.strip()] = value.strip()
|
||||
|
||||
setattr(namespace, self.dest, env_vars)
|
||||
|
||||
|
||||
class KeyValueAction(argparse.Action):
|
||||
"""Custom action to parse key=value pairs."""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
if '=' not in values:
|
||||
parser.error(f"Argument must be in key=value format: {values}")
|
||||
|
||||
key, value = values.split('=', 1)
|
||||
items = getattr(namespace, self.dest, None) or {}
|
||||
items[key] = value
|
||||
setattr(namespace, self.dest, items)
|
||||
|
||||
|
||||
class RangeAction(argparse.Action):
|
||||
"""Custom action to parse ranges like 1-10."""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
if '-' not in values:
|
||||
parser.error(f"Range must be in format start-end: {values}")
|
||||
|
||||
try:
|
||||
start, end = values.split('-')
|
||||
start = int(start)
|
||||
end = int(end)
|
||||
except ValueError:
|
||||
parser.error(f"Invalid range format: {values}")
|
||||
|
||||
if start > end:
|
||||
parser.error(f"Start must be less than or equal to end: {values}")
|
||||
|
||||
ranges = getattr(namespace, self.dest, None) or []
|
||||
ranges.append((start, end))
|
||||
setattr(namespace, self.dest, ranges)
|
||||
|
||||
|
||||
class AppendUniqueAction(argparse.Action):
|
||||
"""Custom action to append unique values only."""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
items = getattr(namespace, self.dest, None) or []
|
||||
if values not in items:
|
||||
items.append(values)
|
||||
setattr(namespace, self.dest, items)
|
||||
|
||||
|
||||
class ValidateAndStoreAction(argparse.Action):
|
||||
"""Custom action that validates before storing."""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
# Custom validation logic
|
||||
if values.startswith('test-'):
|
||||
print(f"Warning: Using test value: {values}")
|
||||
|
||||
# Transform value
|
||||
transformed = values.upper()
|
||||
|
||||
setattr(namespace, self.dest, transformed)
|
||||
|
||||
|
||||
class IncrementAction(argparse.Action):
|
||||
"""Custom action to increment a value."""
|
||||
|
||||
def __init__(self, option_strings, dest, default=0, **kwargs):
|
||||
super().__init__(option_strings, dest, nargs=0, default=default, **kwargs)
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
current = getattr(namespace, self.dest, self.default)
|
||||
setattr(namespace, self.dest, current + 1)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Custom action demonstrations',
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
|
||||
# Load environment file
|
||||
parser.add_argument(
|
||||
'--env-file',
|
||||
action=LoadEnvFileAction,
|
||||
help='Load environment variables from file'
|
||||
)
|
||||
|
||||
# Key-value pairs
|
||||
parser.add_argument(
|
||||
'--config', '-c',
|
||||
action=KeyValueAction,
|
||||
help='Configuration in key=value format (can be used multiple times)'
|
||||
)
|
||||
|
||||
# Range parsing
|
||||
parser.add_argument(
|
||||
'--range', '-r',
|
||||
action=RangeAction,
|
||||
help='Range in start-end format (e.g., 1-10)'
|
||||
)
|
||||
|
||||
# Unique append
|
||||
parser.add_argument(
|
||||
'--tag',
|
||||
action=AppendUniqueAction,
|
||||
help='Add unique tag (duplicates ignored)'
|
||||
)
|
||||
|
||||
# Validate and transform
|
||||
parser.add_argument(
|
||||
'--key',
|
||||
action=ValidateAndStoreAction,
|
||||
help='Key to transform to uppercase'
|
||||
)
|
||||
|
||||
# Custom increment
|
||||
parser.add_argument(
|
||||
'--increment',
|
||||
action=IncrementAction,
|
||||
help='Increment counter'
|
||||
)
|
||||
|
||||
# Parse arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
# Display results
|
||||
print("Custom Actions Results:")
|
||||
|
||||
if args.env_file:
|
||||
print(f"\nEnvironment Variables:")
|
||||
for key, value in args.env_file.items():
|
||||
print(f" {key}={value}")
|
||||
|
||||
if args.config:
|
||||
print(f"\nConfiguration:")
|
||||
for key, value in args.config.items():
|
||||
print(f" {key}={value}")
|
||||
|
||||
if args.range:
|
||||
print(f"\nRanges:")
|
||||
for start, end in args.range:
|
||||
print(f" {start}-{end} (includes {end - start + 1} values)")
|
||||
|
||||
if args.tag:
|
||||
print(f"\nUnique Tags: {', '.join(args.tag)}")
|
||||
|
||||
if args.key:
|
||||
print(f"\nTransformed Key: {args.key}")
|
||||
|
||||
if args.increment:
|
||||
print(f"\nIncrement Count: {args.increment}")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user