Repository: RockefellerArchiveCenter/rac_aspace

Issue:
Add function to open data files and return an iterable
**Is your feature request related to a problem? Please describe.**
To address #30 @daremiyo and I think it would be good to have a function that can turn a file into something that a script can use natively.

**Describe the solution you'd like**
Create a function that takes a filepath for an input file (in CSV or Excel) and returns an iterable that can be used in a script.

Discussion:

Patch:
diff --git a/rac_aspace/serializers.py b/rac_aspace/serializers.py
index 9c327c4..534804f 100644
--- a/rac_aspace/serializers.py
+++ b/rac_aspace/serializers.py
@@ -1,7 +1,7 @@
 import csv
 
 
-class Serializer:
+class BaseSerializer:
 
     def __init__(self, filename, filemode="w"):
         """Sets initial attributes for serializers.
@@ -14,8 +14,6 @@ class Serializer:
             filename (str): a filename at which the data should be serialized.
             filemode (str): Optional argument used when opening files.
         """
-        if filemode.startswith("r"):
-            raise TypeError("Filemode must allow write operations.")
         self.filemode = filemode
         extension = filename.split(".")[-1]
         if extension != self.extension:
@@ -31,6 +29,8 @@ class Serializer:
         Args:
             data (dict or list): a sequence of dicts.
         """
+        if self.filemode.startswith("r"):
+            raise TypeError("Filemode must allow write operations.")
         fieldnames = list(
             data.keys() if isinstance(
                 data, dict) else data[0].keys())
@@ -40,15 +40,22 @@ class Serializer:
             writer.writeheader()
             writer.writerows(data)
 
+    def read_data(self):
+        if not self.filemode.startswith("r"):
+            raise TypeError("Read-only filemode required.")
+        with open(self.filename, self.filemode) as f:
+            reader = csv.DictReader(f)
+            return [row for row in reader]
+
 
-class CSVWriter(Serializer):
+class CSVSerializer(BaseSerializer):
     """Writes data to a CSV file."""
 
     delimiter = ","
     extension = "csv"
 
 
-class TSVWriter(Serializer):
+class TSVSerializer(BaseSerializer):
     """Writes data to a TSV file."""
 
     delimiter = "\t"


Test patch:
diff --git a/tests/test_serializers.py b/tests/test_serializers.py
index 4563388..a47364c 100644
--- a/tests/test_serializers.py
+++ b/tests/test_serializers.py
@@ -39,12 +39,12 @@ class TestSerializers(unittest.TestCase):
                 remove(expected_filepath)
 
     def test_csv_serializer(self):
-        """Tests CSVWriter."""
-        self.check_serializer(serializers.CSVWriter)
+        """Tests CSVSerializer."""
+        self.check_serializer(serializers.CSVSerializer)
 
     def test_tsv_serializer(self):
-        """Tests TSVWriter."""
-        self.check_serializer(serializers.TSVWriter)
+        """Tests TSVSerializer."""
+        self.check_serializer(serializers.TSVSerializer)
 
     def test_filemodes(self):
         """Tests different filemodes.
@@ -53,16 +53,38 @@ class TestSerializers(unittest.TestCase):
         a meaningful exception.
         """
         for filemode in ["a", "a+", "w", "w+"]:
-            for serializer in [serializers.CSVWriter, serializers.TSVWriter]:
+            for serializer in [serializers.CSVSerializer,
+                               serializers.TSVSerializer]:
                 expected_filepath = "test.{}".format(serializer.extension)
                 s = serializer("test", filemode=filemode)
                 s.write_data(self.short_data)
                 self.assertTrue(isfile(expected_filepath))
-                remove(expected_filepath)
+                with self.assertRaises(TypeError):
+                    s.read_data()
         for filemode in ["r", "r+"]:
-            for serializer in [serializers.CSVWriter, serializers.TSVWriter]:
+            for serializer in [serializers.CSVSerializer,
+                               serializers.TSVSerializer]:
+                s = serializer("test", filemode=filemode)
+                read = s.read_data()
+                self.assertIsInstance(read, list)
                 with self.assertRaises(TypeError):
-                    serializer("test", filemode=filemode)
+                    s.write_data(self.short_data)
+        for filename in ["test.tsv", "test.csv"]:
+            remove(filename)
+
+    def test_read_data(self):
+        """Tests correct returned from a CSV or TSV file."""
+        filename = "read_file.csv"
+        fieldnames = list(self.long_data[0].keys())
+        with open(filename, "w") as f:
+            writer = csv.DictWriter(
+                f, fieldnames=fieldnames, delimiter=",")
+            writer.writeheader()
+            writer.writerows(self.long_data)
+        read = serializers.CSVSerializer(filename, filemode="r").read_data()
+        self.assertIsInstance(read, list)
+        self.assertEqual(read, self.long_data)
+        remove(filename)
 
     def tearDown(self):
         for filename in ["spreadsheet.csv", "spreadsheet.tsv"]: