Repository: frictionlessdata/frictionless-py

Issue:
Validation exception: The task has an error: 'list' object has no attribute 'startswith'
I am trying to validate the following resource (A.resource.json):

```js
{
  "encoding": "utf-8-sig",
  "format": "csv",
  "hashing": "md5",
  "name": "a_b_c_1_s",
  "profile": "tabular-data-resource",
  "scheme": "file",
  "path": [
    "A.csv"
  ],
  "layout": {
    "headerRows": [
      4
    ]
  },
  "schema": {
    "primaryKey": "Excel time",
    "fields": [
      {
        "name": "Excel time",
        "type": "number",
        "constraints": {
          "required": true
        }
      },
      {
        "name": "resource1_1_s_mean (°C)",
        "type": "number",
        "constraints": {
          "required": true
        },
        "properties": {
          "Unit": "°C",
          "Groups:0": "group1"
        }
      },
      {
        "name": "resource1_1_s_max (°C)",
        "type": "number",
        "constraints": {
          "required": true
        },
        "properties": {
          "Unit": "°C",
          "Groups:0": "group1"
        }
      }
    ],
    "properties": {
      "my-custom-parameter1": "my-custom-value1",
      "my-custom-parameter2": "my-custom-value2"
    }
  }
}
```

like this:

```python
from pprint import pprint
from frictionless import validate

report = validate('A.resource.json')
pprint(report)
```

And I receive the error 
```python
{'code': 'task-error',
             'description': 'General task-level error.',
             'message': "The task has an error: 'list' object has no attribute "
                        "'startswith'",
             'name': 'Task Error',
             'note': "'list' object has no attribute 'startswith'",
             'tags': []}
```

According to https://specs.frictionlessdata.io/data-resource/#data-location it is OK for the `path` property to be an array but the validation code treats it as single string: The error occurs in `local.py`, method `LocalLoader.read_byte_stream_create` where `if fullpath.startswith(scheme):` is called.

Is this a bug or do I misunderstand the `Data in Multiple Files` feature?`

Thanks,
Apollo3zehn

Discussion:

Patch:
diff --git a/data/issue-991.csv b/data/issue-991.csv
new file mode 100644
index 00000000..9e78f851
--- /dev/null
+++ b/data/issue-991.csv
@@ -0,0 +1,2 @@
+Excel time,resource1_1_s_mean (°C),resource1_1_s_max (°C)
+1,2,3
diff --git a/data/issue-991.resource.json b/data/issue-991.resource.json
new file mode 100644
index 00000000..71d6c3fa
--- /dev/null
+++ b/data/issue-991.resource.json
@@ -0,0 +1,54 @@
+{
+  "encoding": "utf-8-sig",
+  "format": "csv",
+  "hashing": "md5",
+  "name": "a_b_c_1_s",
+  "profile": "tabular-data-resource",
+  "scheme": "file",
+  "path": [
+    "issue-991.csv"
+  ],
+  "layout": {
+    "headerRows": [
+      4
+    ]
+  },
+  "schema": {
+    "primaryKey": "Excel time",
+    "fields": [
+      {
+        "name": "Excel time",
+        "type": "number",
+        "constraints": {
+          "required": true
+        }
+      },
+      {
+        "name": "resource1_1_s_mean (°C)",
+        "type": "number",
+        "constraints": {
+          "required": true
+        },
+        "properties": {
+          "Unit": "°C",
+          "Groups:0": "group1"
+        }
+      },
+      {
+        "name": "resource1_1_s_max (°C)",
+        "type": "number",
+        "constraints": {
+          "required": true
+        },
+        "properties": {
+          "Unit": "°C",
+          "Groups:0": "group1"
+        }
+      }
+    ],
+    "properties": {
+      "my-custom-parameter1": "my-custom-value1",
+      "my-custom-parameter2": "my-custom-value2"
+    }
+  }
+}
diff --git a/frictionless/plugin.py b/frictionless/plugin.py
index 632baa06..627e86ac 100644
--- a/frictionless/plugin.py
+++ b/frictionless/plugin.py
@@ -1,3 +1,6 @@
+# NOTE: implement create_resource so plugins can validate it (see #991)?
+
+
 class Plugin:
     """Plugin representation
 
diff --git a/frictionless/resource.py b/frictionless/resource.py
index edd50a92..df607b68 100644
--- a/frictionless/resource.py
+++ b/frictionless/resource.py
@@ -394,7 +394,13 @@ class Resource(Metadata):
         Returns
             str: resource scheme
         """
-        return self.get("scheme", self.__file.scheme).lower()
+        scheme = self.get("scheme", self.__file.scheme).lower()
+        # NOTE: review this approach (see #991)
+        # NOTE: move to plugins.multipart when plugin.priority/create_resource is implemented
+        if self.multipart and scheme != "multipart":
+            note = f'Multipart resource requires "multipart" scheme but "{scheme}" is set'
+            raise FrictionlessException(errors.SchemeError(note=note))
+        return scheme
 
     @Metadata.property
     def format(self):


Test patch:
diff --git a/tests/validate/test_resource.py b/tests/validate/test_resource.py
index deb6b995..ea66c1ef 100644
--- a/tests/validate/test_resource.py
+++ b/tests/validate/test_resource.py
@@ -1061,6 +1061,11 @@ def test_validate_custom_check_bad_name():
     ]
 
 
+def test_validate_resource_descriptor_type_invalid():
+    report = validate(descriptor="data/table.csv")
+    assert report.flatten() == [[1, None, None, "resource-error"]]
+
+
 # Issues
 
 
@@ -1171,6 +1176,11 @@ def test_validate_resource_header_row_has_first_number_issue_870():
     assert report.valid
 
 
-def test_validate_resource_descriptor_type_invalid():
-    report = validate(descriptor="data/table.csv")
-    assert report.flatten() == [[1, None, None, "resource-error"]]
+def test_validate_resource_array_path_issue_991():
+    report = validate("data/issue-991.resource.json")
+    assert report.flatten(["code", "note"]) == [
+        [
+            "scheme-error",
+            'Multipart resource requires "multipart" scheme but "file" is set',
+        ],
+    ]