Repository: intel/dffml

Issue:
sources: Change `label` to `tag`
The word `label` has machine learning meanings, lets change it to `tag` which is more of what we are talking about anyways



Discussion:

Resolving patch:
diff --git a/dffml/source/csv.py b/dffml/source/csv.py
--- a/dffml/source/csv.py
+++ b/dffml/source/csv.py
@@ -27,7 +27,7 @@ class OpenCSVFile:
     active: int
     lock: asyncio.Lock
     write_back_key: bool = True
-    write_back_label: bool = False
+    write_back_tag: bool = False
 
     async def inc(self):
         async with self.lock:
@@ -40,15 +40,15 @@ async def dec(self):
 
 
 CSV_SOURCE_CONFIG_DEFAULT_KEY = "key"
-CSV_SOURCE_CONFIG_DEFAULT_LABEL = "unlabeled"
-CSV_SOURCE_CONFIG_DEFAULT_LABEL_COLUMN = "label"
+CSV_SOURCE_CONFIG_DEFAULT_tag = "untagged"
+CSV_SOURCE_CONFIG_DEFAULT_tag_COLUMN = "tag"
 
 
 @config
 class CSVSourceConfig(FileSourceConfig):
     key: str = CSV_SOURCE_CONFIG_DEFAULT_KEY
-    label: str = CSV_SOURCE_CONFIG_DEFAULT_LABEL
-    labelcol: str = CSV_SOURCE_CONFIG_DEFAULT_LABEL_COLUMN
+    tag: str = CSV_SOURCE_CONFIG_DEFAULT_tag
+    tagcol: str = CSV_SOURCE_CONFIG_DEFAULT_tag_COLUMN
 
 
 # CSVSource is a bit of a mess
@@ -91,24 +91,24 @@ async def read_csv(self, fd, open_file):
         # Record what headers are present when the file was opened
         if not self.config.key in dict_reader.fieldnames:
             open_file.write_back_key = False
-        if self.config.labelcol in dict_reader.fieldnames:
-            open_file.write_back_label = True
-        # Store all the repos by their label in write_out
+        if self.config.tagcol in dict_reader.fieldnames:
+            open_file.write_back_tag = True
+        # Store all the repos by their tag in write_out
         open_file.write_out = {}
-        # If there is no key track row index to be used as key by label
+        # If there is no key track row index to be used as key by tag
         index = {}
         for row in dict_reader:
-            # Grab label from row
-            label = row.get(self.config.labelcol, self.config.label)
-            if self.config.labelcol in row:
-                del row[self.config.labelcol]
-            index.setdefault(label, 0)
+            # Grab tag from row
+            tag = row.get(self.config.tagcol, self.config.tag)
+            if self.config.tagcol in row:
+                del row[self.config.tagcol]
+            index.setdefault(tag, 0)
             # Grab key from row
-            key = row.get(self.config.key, str(index[label]))
+            key = row.get(self.config.key, str(index[tag]))
             if self.config.key in row:
                 del row[self.config.key]
             else:
-                index[label] += 1
+                index[tag] += 1
             # Repo data we are going to parse from this row (must include
             # features).
             repo_data = {}
@@ -159,18 +159,18 @@ async def read_csv(self, fd, open_file):
             }
             repo_data.update({"prediction": predictions})
             # If there was no data in the row, skip it
-            if not repo_data and key == str(index[label] - 1):
+            if not repo_data and key == str(index[tag] - 1):
                 continue
             # Add the repo to our internal memory representation
-            open_file.write_out.setdefault(label, {})
-            open_file.write_out[label][key] = Repo(key, data=repo_data)
+            open_file.write_out.setdefault(tag, {})
+            open_file.write_out[tag][key] = Repo(key, data=repo_data)
 
     async def load_fd(self, fd):
         """
         Parses a CSV stream into Repo instances
         """
         async with self._open_csv(fd) as open_file:
-            self.mem = open_file.write_out.get(self.config.label, {})
+            self.mem = open_file.write_out.get(self.config.tag, {})
         self.logger.debug("%r loaded %d records", self, len(self.mem))
 
     async def dump_fd(self, fd):
@@ -179,8 +179,8 @@ async def dump_fd(self, fd):
         """
         async with self.OPEN_CSV_FILES_LOCK:
             open_file = self.OPEN_CSV_FILES[self.config.filename]
-            open_file.write_out.setdefault(self.config.label, {})
-            open_file.write_out[self.config.label].update(self.mem)
+            open_file.write_out.setdefault(self.config.tag, {})
+            open_file.write_out[self.config.tag].update(self.mem)
             # Bail if not last open source for this file
             if not (await open_file.dec()):
                 return
@@ -188,11 +188,11 @@ async def dump_fd(self, fd):
             fieldnames = (
                 [] if not open_file.write_back_key else [self.config.key]
             )
-            fieldnames.append(self.config.labelcol)
+            fieldnames.append(self.config.tagcol)
             # Get all the feature names
             feature_fieldnames = set()
             prediction_fieldnames = set()
-            for label, repos in open_file.write_out.items():
+            for tag, repos in open_file.write_out.items():
                 for repo in repos.values():
                     feature_fieldnames |= set(repo.data.features.keys())
                     prediction_fieldnames |= set(repo.data.prediction.keys())
@@ -209,12 +209,12 @@ async def dump_fd(self, fd):
             # Write out the file
             writer = csv.DictWriter(fd, fieldnames=fieldnames)
             writer.writeheader()
-            for label, repos in open_file.write_out.items():
+            for tag, repos in open_file.write_out.items():
                 for repo in repos.values():
                     repo_data = repo.dict()
                     row = {name: "" for name in fieldnames}
-                    # Always write the label
-                    row[self.config.labelcol] = label
+                    # Always write the tag
+                    row[self.config.tagcol] = tag
                     # Write the key if it existed
                     if open_file.write_back_key:
                         row[self.config.key] = repo.key
diff --git a/dffml/source/file.py b/dffml/source/file.py
--- a/dffml/source/file.py
+++ b/dffml/source/file.py
@@ -18,7 +18,7 @@
 @config
 class FileSourceConfig:
     filename: str
-    label: str = "unlabeled"
+    tag: str = "untagged"
     readwrite: bool = False
     allowempty: bool = False
 
diff --git a/dffml/source/json.py b/dffml/source/json.py
--- a/dffml/source/json.py
+++ b/dffml/source/json.py
@@ -73,14 +73,14 @@ async def load_fd(self, fd):
             repos = self.OPEN_JSON_FILES[self.config.filename].data
             self.mem = {
                 key: Repo(key, data=data)
-                for key, data in repos.get(self.config.label, {}).items()
+                for key, data in repos.get(self.config.tag, {}).items()
             }
         LOGGER.debug("%r loaded %d records", self, len(self.mem))
 
     async def dump_fd(self, fd):
         async with self.OPEN_JSON_FILES_LOCK:
             repos = self.OPEN_JSON_FILES[self.config.filename].data
-            repos[self.config.label] = {
+            repos[self.config.tag] = {
                 repo.key: repo.dict() for repo in self.mem.values()
             }
             self.logger.debug(f"{self.config.filename} updated")


Test patch:
diff --git a/dffml/util/testing/source.py b/dffml/util/testing/source.py
--- a/dffml/util/testing/source.py
+++ b/dffml/util/testing/source.py
@@ -125,22 +125,22 @@ async def test_update(self):
                     )
                     await super().test_update()
 
-    async def test_label(self):
+    async def test_tag(self):
         with tempfile.TemporaryDirectory() as testdir:
             self.testfile = os.path.join(testdir, str(random.random()))
-            unlabeled = await self.setUpSource()
-            labeled = await self.setUpSource()
-            labeled.config = labeled.config._replace(label="somelabel")
-            async with unlabeled, labeled:
-                async with unlabeled() as uctx, labeled() as lctx:
+            untagged = await self.setUpSource()
+            tagged = await self.setUpSource()
+            tagged.config = tagged.config._replace(tag="sometag")
+            async with untagged, tagged:
+                async with untagged() as uctx, tagged() as lctx:
                     await uctx.update(
                         Repo("0", data={"features": {"feed": 1}})
                     )
                     await lctx.update(
                         Repo("0", data={"features": {"face": 2}})
                     )
-            async with unlabeled, labeled:
-                async with unlabeled() as uctx, labeled() as lctx:
+            async with untagged, tagged:
+                async with untagged() as uctx, tagged() as lctx:
                     repo = await uctx.repo("0")
                     self.assertIn("feed", repo.features())
                     repo = await lctx.repo("0")
diff --git a/examples/source/test_custom_sqlite.py b/examples/source/test_custom_sqlite.py
--- a/examples/source/test_custom_sqlite.py
+++ b/examples/source/test_custom_sqlite.py
@@ -12,8 +12,8 @@ async def setUpSource(self):
             CustomSQLiteSourceConfig(filename=self.testfile)
         )
 
-    @unittest.skip("Labels not implemented")
-    async def test_label(self):
+    @unittest.skip("tags not implemented")
+    async def test_tag(self):
         """
-        Labels not implemented
+        tags not implemented
         """
diff --git a/service/http/tests/test_routes.py b/service/http/tests/test_routes.py
--- a/service/http/tests/test_routes.py
+++ b/service/http/tests/test_routes.py
@@ -273,9 +273,9 @@ async def test_source(self):
                 self.cli.app["sources"]["salary"].config,
                 CSVSourceConfig(
                     filename="dataset.csv",
-                    label="unlabeled",
+                    tag="untagged",
                     key="key",
-                    labelcol="label",
+                    tagcol="tag",
                     allowempty=True,
                 ),
             )
@@ -360,7 +360,7 @@ async def test_not_found(self):
                     ServerException, f"{check} feed face not found"
                 ):
                     async with self.post(
-                        f"/configure/{check}/feed face/label", json={}
+                        f"/configure/{check}/feed face/tag", json={}
                     ):
                         pass  # pramga: no cov
 
diff --git a/source/mysql/tests/test_source.py b/source/mysql/tests/test_source.py
--- a/source/mysql/tests/test_source.py
+++ b/source/mysql/tests/test_source.py
@@ -76,8 +76,8 @@ def tearDownClass(cls):
     async def setUpSource(self):
         return MySQLSource(self.source_config)
 
-    @unittest.skip("Labels not implemented")
-    async def test_label(self):
+    @unittest.skip("Tags not implemented")
+    async def test_tag(self):
         """
-        Labels not implemented
+        Tags not implemented
         """
diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py
--- a/tests/integration/test_cli.py
+++ b/tests/integration/test_cli.py
@@ -93,10 +93,10 @@ async def test_memory_to_csv(self):
             pathlib.Path(filename).read_text(),
             inspect.cleandoc(
                 """
-                key,label
-                A,unlabeled
-                B,unlabeled
-                C,unlabeled
+                key,tag
+                A,untagged
+                B,untagged
+                C,untagged
                 """
             )
             + "\n",
diff --git a/tests/source/test_csv.py b/tests/source/test_csv.py
--- a/tests/source/test_csv.py
+++ b/tests/source/test_csv.py
@@ -22,45 +22,45 @@ async def setUpSource(self):
             )
         )
 
-    async def test_label(self):
+    async def test_tag(self):
         with tempfile.TemporaryDirectory() as testdir:
             self.testfile = os.path.join(testdir, str(random.random()))
-            unlabeled = await self.setUpSource()
-            labeled = await self.setUpSource()
-            labeled.config = labeled.config._replace(label="somelabel")
-            async with unlabeled, labeled:
-                async with unlabeled() as uctx, labeled() as lctx:
+            untagged = await self.setUpSource()
+            tagged = await self.setUpSource()
+            tagged.config = tagged.config._replace(tag="sometag")
+            async with untagged, tagged:
+                async with untagged() as uctx, tagged() as lctx:
                     await uctx.update(
                         Repo("0", data={"features": {"feed": 1}})
                     )
                     await lctx.update(
                         Repo("0", data={"features": {"face": 2}})
                     )
-                # async with unlabeled, labeled:
-                async with unlabeled() as uctx, labeled() as lctx:
+                # async with untagged, tagged:
+                async with untagged() as uctx, tagged() as lctx:
                     repo = await uctx.repo("0")
                     self.assertIn("feed", repo.features())
                     repo = await lctx.repo("0")
                     self.assertIn("face", repo.features())
             with open(self.testfile, "r") as fd:
                 dict_reader = csv.DictReader(fd, dialect="strip")
-                rows = {row["label"]: {row["key"]: row} for row in dict_reader}
-                self.assertIn("unlabeled", rows)
-                self.assertIn("somelabel", rows)
-                self.assertIn("0", rows["unlabeled"])
-                self.assertIn("0", rows["somelabel"])
-                self.assertIn("feed", rows["unlabeled"]["0"])
-                self.assertIn("face", rows["somelabel"]["0"])
-                self.assertEqual("1", rows["unlabeled"]["0"]["feed"])
-                self.assertEqual("2", rows["somelabel"]["0"]["face"])
+                rows = {row["tag"]: {row["key"]: row} for row in dict_reader}
+                self.assertIn("untagged", rows)
+                self.assertIn("sometag", rows)
+                self.assertIn("0", rows["untagged"])
+                self.assertIn("0", rows["sometag"])
+                self.assertIn("feed", rows["untagged"]["0"])
+                self.assertIn("face", rows["sometag"]["0"])
+                self.assertEqual("1", rows["untagged"]["0"]["feed"])
+                self.assertEqual("2", rows["sometag"]["0"]["face"])
 
     def test_config_default(self):
         config = CSVSource.config(
             parse_unknown("--source-csv-filename", "feedface")
         )
         self.assertEqual(config.filename, "feedface")
-        self.assertEqual(config.label, "unlabeled")
-        self.assertEqual(config.labelcol, "label")
+        self.assertEqual(config.tag, "untagged")
+        self.assertEqual(config.tagcol, "tag")
         self.assertEqual(config.key, "key")
         self.assertFalse(config.readwrite)
         self.assertFalse(config.allowempty)
@@ -70,10 +70,10 @@ def test_config_set(self):
             parse_unknown(
                 "--source-csv-filename",
                 "feedface",
-                "--source-csv-label",
-                "default-label",
-                "--source-csv-labelcol",
-                "dffml_label",
+                "--source-csv-tag",
+                "default-tag",
+                "--source-csv-tagcol",
+                "dffml_tag",
                 "--source-csv-key",
                 "SourceURLColumn",
                 "--source-csv-readwrite",
@@ -81,8 +81,8 @@ def test_config_set(self):
             )
         )
         self.assertEqual(config.filename, "feedface")
-        self.assertEqual(config.label, "default-label")
-        self.assertEqual(config.labelcol, "dffml_label")
+        self.assertEqual(config.tag, "default-tag")
+        self.assertEqual(config.tagcol, "dffml_tag")
         self.assertEqual(config.key, "SourceURLColumn")
         self.assertTrue(config.readwrite)
         self.assertTrue(config.allowempty)
diff --git a/tests/source/test_file.py b/tests/source/test_file.py
--- a/tests/source/test_file.py
+++ b/tests/source/test_file.py
@@ -81,8 +81,8 @@ def test_args(self):
                                     ),
                                     "config": {},
                                 },
-                                "label": {
-                                    "arg": Arg(type=str, default="unlabeled"),
+                                "tag": {
+                                    "arg": Arg(type=str, default="untagged"),
                                     "config": {},
                                 },
                             },
@@ -97,7 +97,7 @@ def test_config_readonly_default(self):
             parse_unknown("--source-file-filename", "feedface")
         )
         self.assertEqual(config.filename, "feedface")
-        self.assertEqual(config.label, "unlabeled")
+        self.assertEqual(config.tag, "untagged")
         self.assertFalse(config.readwrite)
         self.assertFalse(config.allowempty)
 
@@ -106,24 +106,24 @@ def test_config_readonly_set(self):
             parse_unknown(
                 "--source-file-filename",
                 "feedface",
-                "--source-file-label",
-                "default-label",
+                "--source-file-tag",
+                "default-tag",
                 "--source-file-readwrite",
                 "--source-file-allowempty",
             )
         )
         self.assertEqual(config.filename, "feedface")
-        self.assertEqual(config.label, "default-label")
+        self.assertEqual(config.tag, "default-tag")
         self.assertTrue(config.readwrite)
         self.assertTrue(config.allowempty)
 
     def config(
-        self, filename, label="unlabeled", readwrite=True, allowempty=True
+        self, filename, tag="untagged", readwrite=True, allowempty=True
     ):
         return FileSourceConfig(
             filename=filename,
             readwrite=readwrite,
-            label=label,
+            tag=tag,
             allowempty=allowempty,
         )
 
diff --git a/tests/test_cli.py b/tests/test_cli.py
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -57,7 +57,7 @@ async def setUp(self):
         contents = json.loads(Path(self.sconfig.filename).read_text())
         # Ensure there are repos in the file
         self.assertEqual(
-            len(contents.get(self.sconfig.label)),
+            len(contents.get(self.sconfig.tag)),
             len(self.repos),
             "ReposTestCase JSON file erroneously initialized as empty",
         )
@@ -146,14 +146,14 @@ def opimp_load(loading=None):
 
 
 class TestMerge(ReposTestCase):
-    async def test_json_label(self):
+    async def test_json_tag(self):
         await Merge.cli(
             "dest=json",
             "src=json",
             "-source-dest-filename",
             self.temp_filename,
-            "-source-dest-label",
-            "somelabel",
+            "-source-dest-tag",
+            "sometag",
             "-source-src-filename",
             self.temp_filename,
             "-source-src-allowempty",
@@ -161,20 +161,18 @@ async def test_json_label(self):
             "-source-src-readwrite",
             "-source-dest-readwrite",
         )
-        # Check the unlabeled source
-        with self.subTest(labeled=None):
+        # Check the untagged source
+        with self.subTest(tagged=None):
             async with JSONSource(
                 FileSourceConfig(filename=self.temp_filename)
             ) as source:
                 async with source() as sctx:
                     repos = [repo async for repo in sctx.repos()]
                     self.assertEqual(len(repos), len(self.repos))
-        # Check the labeled source
-        with self.subTest(labeled="somelabel"):
+        # Check the tagged source
+        with self.subTest(tagged="sometag"):
             async with JSONSource(
-                FileSourceConfig(
-                    filename=self.temp_filename, label="somelabel"
-                )
+                FileSourceConfig(filename=self.temp_filename, tag="sometag")
             ) as source:
                 async with source() as sctx:
                     repos = [repo async for repo in sctx.repos()]
@@ -199,13 +197,13 @@ async def test_json_to_csv(self):
             contents = Path(csv_tempfile).read_text()
             self.assertEqual(
                 contents,
-                "key,label\n"
-                + "\n".join([f"{repo.key},unlabeled" for repo in self.repos])
+                "key,tag\n"
+                + "\n".join([f"{repo.key},untagged" for repo in self.repos])
                 + "\n",
                 "Incorrect data in csv file",
             )
 
-    async def test_csv_label(self):
+    async def test_csv_tag(self):
         with non_existant_tempfile() as csv_tempfile:
             # Move the pre-populated json data to a csv source
             with self.subTest(json_to_csv=True):
@@ -221,15 +219,15 @@ async def test_csv_label(self):
                     "-source-src-readwrite",
                     "-source-dest-readwrite",
                 )
-            # Merge one label to another within the same file
+            # Merge one tag to another within the same file
             with self.subTest(merge_same_file=True):
                 await Merge.cli(
                     "dest=csv",
                     "src=csv",
                     "-source-dest-filename",
                     csv_tempfile,
-                    "-source-dest-label",
-                    "somelabel",
+                    "-source-dest-tag",
+                    "sometag",
                     "-source-src-filename",
                     csv_tempfile,
                     "-source-src-allowempty",
@@ -238,10 +236,10 @@ async def test_csv_label(self):
                     "-source-dest-readwrite",
                 )
             contents = Path(csv_tempfile).read_text()
-            self.assertIn("unlabeled", contents)
-            self.assertIn("somelabel", contents)
-            # Check the unlabeled source
-            with self.subTest(labeled=None):
+            self.assertIn("untagged", contents)
+            self.assertIn("sometag", contents)
+            # Check the untagged source
+            with self.subTest(tagged=None):
                 async with CSVSource(
                     CSVSourceConfig(filename=csv_tempfile)
                 ) as source:
@@ -249,19 +247,19 @@ async def test_csv_label(self):
                         repos = [repo async for repo in sctx.repos()]
                         self.assertEqual(len(repos), len(self.repos))
             contents = Path(csv_tempfile).read_text()
-            self.assertIn("somelabel", contents)
-            self.assertIn("unlabeled", contents)
-            # Check the labeled source
-            with self.subTest(labeled="somelabel"):
+            self.assertIn("sometag", contents)
+            self.assertIn("untagged", contents)
+            # Check the tagged source
+            with self.subTest(tagged="sometag"):
                 async with CSVSource(
-                    CSVSourceConfig(filename=csv_tempfile, label="somelabel")
+                    CSVSourceConfig(filename=csv_tempfile, tag="sometag")
                 ) as source:
                     async with source() as sctx:
                         repos = [repo async for repo in sctx.repos()]
                         self.assertEqual(len(repos), len(self.repos))
             contents = Path(csv_tempfile).read_text()
-            self.assertIn("somelabel", contents)
-            self.assertIn("unlabeled", contents)
+            self.assertIn("sometag", contents)
+            self.assertIn("untagged", contents)
 
 
 class TestListRepos(ReposTestCase):