Repository: zimeon/ocfl-py

Issue:
Add check for non-unique logical paths
See https://github.com/OCFL/fixtures/pull/65 which currently gets incorrectly reported as valid

Discussion:
coveralls: 
[![Coverage Status](https://coveralls.io/builds/39029172/badge)](https://coveralls.io/builds/39029172)

Coverage increased (+0.01%) to 94.646% when pulling **cdcd6d2cdc923a3db5f20eae7cd28964b574fe1e on issue-39** into **0c7d93fe38bb3b58a9c54e7610913379b0631a51 on develop**.


Patch:
diff --git a/ocfl/data/validation-errors.json b/ocfl/data/validation-errors.json
index 64f9dbf..b2e50fd 100644
--- a/ocfl/data/validation-errors.json
+++ b/ocfl/data/validation-errors.json
@@ -483,7 +483,13 @@
        "en": "OCFL Object %s inventory %s version block has message key with value that isn't a string"
     }
   },
-  "E095": {
+  "E095a": {
+    "params": ["where", "version", "path"],
+    "description": {
+       "en": "OCFL Object %s inventory version %s state has logical path %s used more than once."
+    }
+  },
+  "E095b": {
     "params": ["where", "version", "path"],
     "description": {
        "en": "OCFL Object %s inventory version %s state has logical path %s used as both a directory and a file path."
diff --git a/ocfl/inventory_validator.py b/ocfl/inventory_validator.py
index 83a0f6e..4453b22 100644
--- a/ocfl/inventory_validator.py
+++ b/ocfl/inventory_validator.py
@@ -334,7 +334,10 @@ class InventoryValidator():
                     self.error('E050e', version=version, digest=digest)
                 else:
                     for path in state[digest]:
-                        self.check_logical_path(path, version, logical_paths, logical_directories)
+                        if path in logical_paths:
+                            self.error("E095a", version=version, path=path)
+                        else:
+                            self.check_logical_path(path, version, logical_paths, logical_directories)
                     if digest not in unnormalized_digests:
                         # Exact string value must match, not just normalized
                         self.error("E050f", version=version, digest=digest)
@@ -343,7 +346,7 @@ class InventoryValidator():
             # Check for conflicting logical paths
             for path in logical_directories:
                 if path in logical_paths:
-                    self.error("E095", version=version, path=path)
+                    self.error("E095b", version=version, path=path)
         return digests
 
     def check_content_paths_map_to_versions(self, manifest_files, all_versions):
@@ -380,7 +383,7 @@ class InventoryValidator():
         return r'''^.*$'''
 
     def check_logical_path(self, path, version, logical_paths, logical_directories):
-        """Check logical path and accumulate paths/directories for E095 check.
+        """Check logical path and accumulate paths/directories for E095b check.
 
         logical_paths and logical_directories are expected to be sets.
 


Test patch:
diff --git a/tests/test_validator.py b/tests/test_validator.py
index c1a852c..daa6589 100644
--- a/tests/test_validator.py
+++ b/tests/test_validator.py
@@ -55,8 +55,8 @@ class TestAll(unittest.TestCase):
                            # 'E092_algorithm_change_incorrect_digest': ['E092'],  FIXME https://github.com/OCFL/fixtures/pull/67
                            'E093_fixity_digest_mismatch': ['E093a'],
                            'E094_message_not_a_string': ['E094'],
-                           'E095_conflicting_logical_paths': ['E095'],
-                           # 'E095_non_unique_logical_paths': ['E095'],  FIXME https://github.com/zimeon/ocfl-py/issues/39
+                           'E095_conflicting_logical_paths': ['E095b'],
+                           'E095_non_unique_logical_paths': ['E095a'],
                            'E096_manifest_repeated_digest': ['E096'],
                            'E096_manifest_duplicate_digests': ['E096'],
                            'E097_fixity_repeated_digest': ['E097'],