ArgumentBuilder Python 3.8+

Guarantees consistency of arguments for the Operating System β€” smart argument & flag builder with Unix/Windows style support.

πŸ“– Overview

ArgumentBuilder is a fluent, chainable builder class designed to construct command-line argument lists reliably. It automatically flattens nested sequences, converts values to strings, skips empty or None entries, and supports both Unix (--flag) and Windows (/flag) argument styles. Perfect for building subprocess calls, CLI wrappers, or any OS-level command arguments.

✨ Key Features:
  • βœ… Flattens lists/tuples recursively
  • βœ… Ignores None and empty strings
  • βœ… Dual style: Unix (--flag) or Windows (/flag)
  • βœ… Method chaining for elegant construction
  • βœ… Type-safe: returns List[str] on build

βš™οΈ Constructor

__init__(style: str = "unix")

Initializes a new ArgumentBuilder instance with the specified argument style.

  • style – str, optional. Determines flag prefix: "unix" β†’ -- (default), "windows" β†’ /.
  • Returns – ArgumentBuilder instance.
# Unix style (default)
builder = ArgumentBuilder()
# Windows style
win_builder = ArgumentBuilder(style="windows")

πŸ”§ Public Methods

add_arg(value: Any) -> ArgumentBuilder

Adds an argument to the internal list. Automatically flattens list or tuple structures, converts any value to string, strips whitespace, and skips None or empty strings after stripping. This method is chainable.

  • value – Any type: string, number, boolean, list, tuple, etc. None or empty values are ignored.
  • Returns – self (fluent interface).
πŸ“ Example:
builder = ArgumentBuilder()
builder.add_arg("ls").add_arg(["-l", "-a"]).add_arg(None).add_arg("--color")
# Resulting args: ["ls", "-l", "-a", "--color"]

add_flag(name: str, value: Any = None) -> ArgumentBuilder

Adds a flag (option) with an optional value. The flag name is automatically cleaned (trims spaces, replaces spaces with underscores). The prefix depends on the style parameter (-- for Unix, / for Windows). If a value is provided, it is added as a separate argument after the flag.

  • name – Flag name (e.g., "verbose", "output file" β†’ normalized to "output_file").
  • value – Optional value associated with the flag. If not None, appended as next argument.
  • Returns – self for chaining.
πŸ“ Example:
builder = ArgumentBuilder(style="unix")
builder.add_flag("verbose").add_flag("output", "result.txt")
# Result: ["--verbose", "--output", "result.txt"]

win_builder = ArgumentBuilder(style="windows")
win_builder.add_flag("recursive", True)
# Result: ["/recursive", "True"]

build() -> List[str]

Finalizes the argument building process and returns the constructed list of string arguments. This method does not alter the builder state; you can continue adding arguments after calling build().

  • Returns – List[str] containing all accumulated, sanitized arguments.
args = ArgumentBuilder().add_arg("echo").add_flag("message", "hello").build()
print(args) # ['echo', '--message', 'hello']

πŸ’‘ Practical Usage Example

Below is a complete example demonstrating how ArgumentBuilder can be used to construct complex command-line invocations for different operating systems while handling nested data structures gracefully.

from typing import List
import subprocess

# Build arguments for a 'find' command (Unix style)
builder = ArgumentBuilder(style="unix")
builder.add_arg("find") \
.add_arg("/home/user") \
.add_flag("type", "f") \
.add_flag("name", "*.py") \
.add_arg(["-exec", "grep", "-l", "TODO", "{}", ";"])

cmd: List[str] = builder.build()
print("Generated command:", cmd)
# Output: ['find', '/home/user', '--type', 'f', '--name', '*.py', '-exec', 'grep', '-l', 'TODO', '{}', ';']

# Windows style with flags
win_builder = ArgumentBuilder(style="windows")
win_builder.add_arg("dir") \
.add_flag("sort", "name") \
.add_flag("reverse")
print(win_builder.build()) # ['dir', '/sort', 'name', '/reverse']

πŸ” The builder intelligently handles nested sequences and automatically strips empty strings, making it robust for dynamic argument generation.

πŸ“„ API Reference & Behavior

MethodParametersDescriptionReturn
__init__style: str = "unix"Constructor. Style 'unix' => '--flag', 'windows' => '/flag'.ArgumentBuilder
add_argvalue: AnyAdds argument flattening iterables, converting to string, ignoring None/empty.self
add_flagname: str, value: Any = NoneAdds a flag with optional value. Normalizes name (spaces→underscores).self
buildNoneReturns the built argument list as List[str].List[str]

🧠 Internal Logic Notes

πŸ” Edge Cases & Advanced Behavior

Handling nested structures & mixed types

builder = ArgumentBuilder()
builder.add_arg(["git", "commit", ["-m", "Initial commit"]])
builder.add_flag("amend").add_arg(None).add_flag("no-verify")
print(builder.build())
# Output: ['git', 'commit', '-m', 'Initial commit', '--amend', '--no-verify']

⚠️ Note: Passing a boolean value like True or False will be stringified ("True" / "False"). If you need special handling, convert manually before adding.

Windows style with numeric values

win = ArgumentBuilder(style="windows")
win.add_arg("ping").add_flag("n", 5).add_arg("127.0.0.1")
print(win.build()) # ['ping', '/n', '5', '127.0.0.1']