Skip to content

Commit

Permalink
Added multiple file export at once
Browse files Browse the repository at this point in the history
  • Loading branch information
jmwright committed Jul 31, 2024
1 parent c7a5f5c commit 5f1be34
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 21 deletions.
92 changes: 71 additions & 21 deletions src/cq_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,11 @@ def get_params_from_file(param_json_path, errfile):

def main():
outfile = None
outfiles = None
errfile = None
codec_module = None
codecs = None
active_codecs = None
params = {}
output_opts = {}

Expand All @@ -155,7 +158,7 @@ def main():
)
parser.add_argument(
"--codec",
help="The codec to use when converting the CadQuery output. Must match the name of a codec file in the cqcodecs directory.",
help="The codec to use when converting the CadQuery output. Must match the name of a codec file in the cqcodecs directory. Multiple codecs can be specified, separated by the colon (;) character. The number of codecs must match the number of output files (outfile parameter).",
)
parser.add_argument(
"--getparams",
Expand All @@ -164,7 +167,7 @@ def main():
parser.add_argument("--infile", help="The input CadQuery script to convert.")
parser.add_argument(
"--outfile",
help="File to write the converted CadQuery output to. Prints to stdout if not specified.",
help="File to write the converted CadQuery output to. Prints to stdout if not specified. Multiple output files can be specified, separated by the colon (;) character. The number of codecs (codec parameter) must match the number of output files.",
)
parser.add_argument(
"--errfile",
Expand Down Expand Up @@ -210,6 +213,11 @@ def main():
if args.outfile != None:
outfile = args.outfile

# Handle the case of multiple outfiles
if ";" in outfile:
outfiles = outfile.split(";")
outfile = outfiles[0]

#
# Errfile handling
#
Expand Down Expand Up @@ -321,6 +329,28 @@ def main():
# Save the requested codec for later
codec = args.codec

# Handle multiple output files
if ";" in codec:
codecs = codec.split(";")
codec = codecs[0]

# Do the first check to make sure the codecs match the number of output files
if (outfiles != None and codecs == None) or (outfiles == None and codecs != None):
print(
"The number of codecs does not match the number of output files.",
file=sys.stderr,
)
sys.exit(4)

# Make sure the codecs match the number of output files
if outfiles != None and codecs != None:
if len(outfiles) != len(codecs):
print(
"The number of codecs does not match the number of output files.",
file=sys.stderr,
)
sys.exit(4)

# Attempt to auto-detect the codec if the user has not set the option
if args.outfile != None and args.codec == None:
# Determine the codec from the file extension
Expand Down Expand Up @@ -351,6 +381,16 @@ def main():
if codec in key:
codec_module = loaded_codecs[key]

# Handle there being multiple codecs
if codecs != None:
for cur_codec in codecs:
for key in loaded_codecs:
# Check to make sure that the requested codec exists
if cur_codec in key:
if active_codecs == None:
active_codecs = []
active_codecs.append(loaded_codecs["cq_codec_" + cur_codec])

#
# Infile handling
#
Expand Down Expand Up @@ -451,26 +491,36 @@ def main():
#
# Build, parse and let the selected codec convert the CQ output
try:
# Use the codec plugin to do the conversion
converted = codec_module.convert(build_result, outfile, errfile, output_opts)

# If converted is None, assume that the output was written to file directly by the codec
if converted != None:
# Write the converted output to the appropriate place based on the command line arguments
if outfile == None:
print(converted)
else:
if isinstance(converted, str):
with open(outfile, "w") as file:
file.write(converted)
elif isinstance(converted, (bytes, bytearray)):
with open(outfile, "wb") as file:
file.write(converted)
# Handle the case of multiple output files
if outfiles == None:
outfiles = [outfile]

# Step through all of the potential output files
for i in range(len(outfiles)):
outfile = outfiles[i]
if len(outfiles) > 1:
codec_module = active_codecs[i]

# Use the codec plugin to do the conversion
converted = codec_module.convert(build_result, outfile, errfile, output_opts)

# If converted is None, assume that the output was written to file directly by the codec
if converted != None:
# Write the converted output to the appropriate place based on the command line arguments
if outfile == None:
print(converted)
else:
raise TypeError(
"Expected converted output to be str, bytes, or bytearray. Got '%s'"
% type(converted).__name__
)
if isinstance(converted, str):
with open(outfile, "w") as file:
file.write(converted)
elif isinstance(converted, (bytes, bytearray)):
with open(outfile, "wb") as file:
file.write(converted)
else:
raise TypeError(
"Expected converted output to be str, bytes, or bytearray. Got '%s'"
% type(converted).__name__
)

except Exception:
out_tb = traceback.format_exc()
Expand Down
51 changes: 51 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,54 @@ def test_expression_argument():

# cq-cli invocation should fail
assert exitcode == 200


def test_multiple_outfiles():
"""
Tests the CLI with multiple output files specified.
"""
test_file = helpers.get_test_file_location("cube.py")

# Get a temporary output file location
temp_dir = tempfile.gettempdir()
temp_file_step = os.path.join(temp_dir, "temp_test_11.step")
temp_file_stl = os.path.join(temp_dir, "temp_test_11.stl")
temp_paths = temp_file_step + ";" + temp_file_stl

command = [
"python",
"src/cq_cli/main.py",
"--codec",
"step;stl",
"--infile",
test_file,
"--outfile",
temp_paths,
]
out, err, exitcode = helpers.cli_call(command)
assert exitcode == 0

def test_multiple_outfiles_codec_mismatch():
"""
Tests the CLI with multiple output files specified and a different number of codecs specified.
"""
test_file = helpers.get_test_file_location("cube.py")

# Get a temporary output file location
temp_dir = tempfile.gettempdir()
temp_file_step = os.path.join(temp_dir, "temp_test_11.step")
temp_file_stl = os.path.join(temp_dir, "temp_test_11.stl")
temp_paths = temp_file_step + ";" + temp_file_stl

command = [
"python",
"src/cq_cli/main.py",
"--codec",
"step",
"--infile",
test_file,
"--outfile",
temp_paths,
]
out, err, exitcode = helpers.cli_call(command)
assert exitcode == 4

0 comments on commit 5f1be34

Please sign in to comment.