Repository: A1fus/csv-parakeet (language: python)

Issue:
Add option to read multiple files and combine into a single output



Discussion / hints:

Fix patch:
diff --git a/src/csv_parakeet/console.py b/src/csv_parakeet/console.py
index ca32d05..857abef 100644
--- a/src/csv_parakeet/console.py
+++ b/src/csv_parakeet/console.py
@@ -7,33 +7,40 @@
 @click.group()
 @click.version_option(version=__version__)
 def parakeet() -> None:
-    """Tool to easily convert between CSV and parquet files"""
+    """Tool to easily convert between CSV and Parquet files"""
     return None  # pragma: no cover
 
 
 @parakeet.command()
-@click.argument("file_in", type=click.Path(exists=True), nargs=1)
+@click.argument("file_in", type=click.Path(exists=True), nargs=-1)
 @click.argument("file_out", type=click.Path(), nargs=1)
 def c2p(file_in, file_out):
-    """Convert a CSV file to parquet format
+    """Convert a CSV file to Parquet format
 
     \b
     Arguments:
-        FILE_IN: path to a csv file
-        FILE_OUT: desired path for parquet output
+        FILE_IN: Path to CSV files. If more than one path is given the CSV files are
+        concatenated together.
+        FILE_OUT: Desired path for Parquet output
     """
-    pd.read_csv(file_in).to_parquet(path=file_out, index=False)
+    pd.concat([pd.read_csv(path) for path in file_in], ignore_index=True).to_parquet(
+        path=file_out, index=False
+    )
 
 
 @parakeet.command()
-@click.argument("file_in", type=click.Path(exists=True), nargs=1)
+@click.argument("file_in", type=click.Path(exists=True), nargs=-1)
 @click.argument("file_out", type=click.Path(), nargs=1)
 def p2c(file_in, file_out):
-    """Convert a parqet file to CSV format
+    """Convert a Parquet file to CSV format
 
     \b
     Arguments:
-        FILE_IN: path to a parquet file
-        FILE_OUT: desired path for csv output
+        FILE_IN: Path to Parquet files. If more than one path is given the Parquet
+        files are concatenated together.
+
+        FILE_OUT: Desired path for CSV output
     """
-    pd.read_parquet(file_in).to_csv(path_or_buf=file_out, index=False)
+    pd.concat([pd.read_parquet(path) for path in file_in], ignore_index=True).to_csv(
+        path_or_buf=file_out, index=False
+    )


Test patch:
diff --git a/tests/test_console.py b/tests/test_console.py
index d59d7f1..660354e 100644
--- a/tests/test_console.py
+++ b/tests/test_console.py
@@ -17,8 +17,17 @@ def test_df() -> pd.DataFrame:
 def setup_function():
     os.makedirs("./testfiles", exist_ok=True)
     input_df = pd.DataFrame(data={"a": [0, 1, 2]})
+    input_df_2 = pd.DataFrame(data={"a": [4, 5, 6]})
     input_df.to_csv("./testfiles/test_input.csv", index=False)
+    input_df_2.to_csv("./testfiles/test_input_2.csv", index=False)
     input_df.to_parquet("./testfiles/test_input.parquet", index=False)
+    input_df_2.to_parquet("./testfiles/test_input_2.parquet", index=False)
+    pd.concat([input_df, input_df_2], ignore_index=True).to_parquet(
+        "./testfiles/expected_output_concat.parquet", index=False
+    )
+    pd.concat([input_df, input_df_2], ignore_index=True).to_csv(
+        "./testfiles/expected_output_concat.csv", index=False
+    )
 
 
 def teardown_function():
@@ -27,21 +36,6 @@ def teardown_function():
         shutil.rmtree(dirpath)
 
 
-def test_parakeet_succeeds():
-    runner = click.testing.CliRunner()
-    result = runner.invoke(console.parakeet)
-    assert result.exit_code == 0
-
-
-def test_c2p_succeeds():
-    runner = click.testing.CliRunner()
-    result = runner.invoke(
-        console.c2p,
-        args=["testfiles/test_input.csv", "testfiles/test_succeeds.parquet"],
-    )
-    assert result.exit_code == 0
-
-
 def test_c2p_output_correct(test_df):
     runner = click.testing.CliRunner()
     runner.invoke(
@@ -52,6 +46,21 @@ def test_c2p_output_correct(test_df):
     pd.testing.assert_frame_equal(saved_df, input_df)
 
 
+def test_c2p_multifile_output_correct(test_df):
+    runner = click.testing.CliRunner()
+    runner.invoke(
+        console.c2p,
+        args=[
+            "testfiles/test_input.csv",
+            "testfiles/test_input_2.csv",
+            "testfiles/test_output_concat.parquet",
+        ],
+    )
+    saved_df = pd.read_parquet("testfiles/test_output_concat.parquet")
+    expected_df = pd.read_parquet("testfiles/expected_output_concat.parquet")
+    pd.testing.assert_frame_equal(saved_df, expected_df)
+
+
 def test_p2c_output_correct(test_df):
     runner = click.testing.CliRunner()
     runner.invoke(
@@ -60,3 +69,18 @@ def test_p2c_output_correct(test_df):
     saved_df = pd.read_csv("testfiles/test_output.csv")
     input_df = test_df
     pd.testing.assert_frame_equal(saved_df, input_df)
+
+
+def test_p2c_multifile_output_correct(test_df):
+    runner = click.testing.CliRunner()
+    runner.invoke(
+        console.p2c,
+        args=[
+            "testfiles/test_input.parquet",
+            "testfiles/test_input_2.parquet",
+            "testfiles/test_output_concat.csv",
+        ],
+    )
+    saved_df = pd.read_csv("testfiles/test_output_concat.csv")
+    expected_df = pd.read_csv("testfiles/expected_output_concat.csv")
+    pd.testing.assert_frame_equal(saved_df, expected_df)