@@ -464,15 +464,41 @@ def cli(opts: argparse.Namespace, args: Sequence[str]) -> int:
464464 template_path : str | None = None
465465
466466 if opts .stream :
467- # Stream mode: read template from stdin, no data file
467+ # Stream mode: read template from stdin, all args are data files
468468 template_string = sys .stdin .read ()
469- data : dict | str = {}
469+ data_files = args
470470 else :
471- template_path_arg , data = args
471+ # Normal mode: first arg is template, rest are data files
472+ template_path_arg = args [0 ]
473+ data_files = args [1 :]
474+ template_path = os .path .abspath (template_path_arg )
475+
476+ data : dict = {}
477+
478+ # Determine if we're reading from stdin or files
479+ if not data_files :
480+ # No data files specified
481+ if opts .stream :
482+ # In stream mode, stdin is used for template, so no data
483+ data_files = []
484+ else :
485+ # Normal mode, read data from stdin
486+ data_files = ["-" ]
487+
488+ # Check for invalid mixing of stdin and files
489+ has_stdin = any (f in ("-" , "" ) for f in data_files )
490+ if has_stdin and len (data_files ) > 1 :
491+ sys .stderr .write ("ERROR: Cannot mix stdin (-) with file arguments\n " )
492+ return 1
493+
494+ # Load and merge multiple data files
495+ for data_file in data_files :
472496 format = opts .format
473- if data in ("-" , "" ):
474- if data == "-" or (data == "" and not sys .stdin .isatty ()):
475- data = sys .stdin .read ()
497+ data_content = ""
498+
499+ if data_file in ("-" , "" ):
500+ if data_file == "-" or (data_file == "" and not sys .stdin .isatty ()):
501+ data_content = sys .stdin .read ()
476502 if format == "auto" :
477503 # default to yaml first if available since yaml
478504 # is a superset of json
@@ -481,7 +507,7 @@ def cli(opts: argparse.Namespace, args: Sequence[str]) -> int:
481507 else :
482508 format = "json"
483509 else :
484- path = os .path .join (os .getcwd (), os .path .expanduser (data ))
510+ path = os .path .join (os .getcwd (), os .path .expanduser (data_file ))
485511 if format == "auto" :
486512 ext = os .path .splitext (path )[1 ][1 :]
487513 if has_format (ext ):
@@ -490,11 +516,9 @@ def cli(opts: argparse.Namespace, args: Sequence[str]) -> int:
490516 raise InvalidDataFormat (ext )
491517
492518 with open (path ) as fp :
493- data = fp .read ()
494-
495- template_path = os .path .abspath (template_path_arg )
519+ data_content = fp .read ()
496520
497- if data :
521+ if data_content :
498522 try :
499523 fn , except_exc , raise_exc = get_format (format )
500524 except InvalidDataFormat :
@@ -510,11 +534,10 @@ def cli(opts: argparse.Namespace, args: Sequence[str]) -> int:
510534 raise InvalidDataFormat ("json5: install json5 to fix" )
511535 raise
512536 try :
513- data = fn (data ) or {}
537+ parsed = fn (data_content ) or {}
538+ deep_merge (data , parsed )
514539 except except_exc :
515- raise raise_exc (f"{ data [:60 ]} ..." )
516- else :
517- data = {}
540+ raise raise_exc (f"{ data_content [:60 ]} ..." )
518541
519542 extensions = []
520543 for ext in opts .extensions :
@@ -763,16 +786,13 @@ def main() -> None:
763786 dest = "stream" ,
764787 )
765788 parser .add_argument ("template" , nargs = "?" , help = argparse .SUPPRESS )
766- parser .add_argument ("data" , nargs = "? " , help = argparse .SUPPRESS )
789+ parser .add_argument ("data" , nargs = "* " , help = argparse .SUPPRESS )
767790 opts = parser .parse_args ()
768- args = [value for value in ( opts .template , opts .data ) if value is not None ]
791+ args = [opts .template ] + list ( opts .data ) if opts . template else [ ]
769792
770793 opts .extensions = set (opts .extensions )
771794
772- if opts .stream :
773- # Stream mode: no positional args needed
774- args = []
775- else :
795+ if not opts .stream :
776796 if len (args ) == 0 :
777797 parser .print_help ()
778798 sys .exit (1 )
0 commit comments