Repository: frictionlessdata/frictionless-py

Issue:
Fix resource.to_json/yaml when resource.data is not a list
# Overview

ATM it fails e.g. `to_yaml` after transform. In general, think about how to improve UX for resource after transform (they are inline)


Discussion:

Patch:
diff --git a/frictionless/helpers.py b/frictionless/helpers.py
index fb22133a..c5c9befa 100644
--- a/frictionless/helpers.py
+++ b/frictionless/helpers.py
@@ -72,18 +72,6 @@ def deepfork(value):
     return value
 
 
-def deepsafe(value):
-    if isinstance(value, dict):
-        value = {key: deepsafe(value) for key, value in value.items()}
-    elif isinstance(value, list):
-        value = [deepsafe(value) for value in value]
-    elif isinstance(value, set):
-        value = {deepsafe(value) for value in value}
-    elif isinstance(value, io.BufferedRandom):
-        value = "memory"
-    return value
-
-
 def import_from_plugin(name, *, plugin):
     try:
         return import_module(name)
diff --git a/frictionless/metadata.py b/frictionless/metadata.py
index 306b9c5a..14f484c2 100644
--- a/frictionless/metadata.py
+++ b/frictionless/metadata.py
@@ -127,7 +127,7 @@ class Metadata(helpers.ControlledDict):
         Raises:
             FrictionlessException: on any error
         """
-        text = yaml.dump(helpers.deepsafe(self.to_dict()), Dumper=IndentDumper)
+        text = yaml.dump(self.to_dict(), Dumper=IndentDumper)
         if path:
             try:
                 helpers.write_file(path, text)
diff --git a/frictionless/resource.py b/frictionless/resource.py
index 2dab5985..b3d2fce4 100644
--- a/frictionless/resource.py
+++ b/frictionless/resource.py
@@ -1076,14 +1076,20 @@ class Resource(Metadata):
 
     # Import/Export
 
+    def to_dict(self):
+        # Data can be not serializable (generators/functions)
+        descriptor = super().to_dict()
+        data = descriptor.pop("data", None)
+        if isinstance(data, list):
+            descriptor["data"] = data
+        return descriptor
+
     def to_copy(self, **options):
         """Create a copy of the resource"""
         descriptor = self.to_dict()
-        # Data can be not serializable (generators/functions)
-        data = descriptor.pop("data", None)
         return Resource(
             descriptor,
-            data=data,
+            data=self.data,
             basepath=self.__basepath,
             onerror=self.__onerror,
             trusted=self.__trusted,


Test patch:
diff --git a/tests/test_resource.py b/tests/test_resource.py
index 17b19315..3d07b12e 100644
--- a/tests/test_resource.py
+++ b/tests/test_resource.py
@@ -2467,6 +2467,20 @@ def test_resource_to_yaml(tmpdir):
         assert resource == yaml.safe_load(file)
 
 
+def test_to_json_with_resource_data_is_not_a_list_issue_693():
+    data = lambda: [["id", "name"], [1, "english"], [2, "german"]]
+    resource = Resource(data=data)
+    text = resource.to_json()
+    assert text == "{}"
+
+
+def test_to_yaml_with_resource_data_is_not_a_list_issue_693():
+    data = lambda: [["id", "name"], [1, "english"], [2, "german"]]
+    resource = Resource(data=data)
+    text = resource.to_yaml()
+    assert text == "{}\n"
+
+
 # Metadata