Repository: frictionlessdata/frictionless-py

Issue:
`to_pandas` breaks for resources without types in `schema.fields`
# Overview

Here's an example resource from [open-numbers](https://github.com/open-numbers/ddf--open_numbers--world_development_indicators)

```
{'name': 'ddf--datapoints--ag_agr_trac_no--by--geo--time',
 'path': 'datapoints/ddf--datapoints--ag_agr_trac_no--by--geo--time.csv',
 'schema': {'fields': [{'name': 'geo'},
                       {'name': 'time'},
                       {'name': 'ag_agr_trac_no'}],
            'primaryKey': ['geo', 'time']}}
```

This used to work with previous versions, but now raises an error with

```
  File "/Users/mojmir/projects/etl/etl/steps/data/open_numbers/open_numbers/latest/open_numbers__world_development_indicators.py", line 61, in run
    df = resource.to_pandas()
  File "/Users/mojmir/projects/etl/.venv/lib/python3.9/site-packages/frictionless/resource/resource.py", line 1203, in to_pandas
    target = self.write(Resource(format="pandas", dialect=dialect))
  File "/Users/mojmir/projects/etl/.venv/lib/python3.9/site-packages/frictionless/resource/resource.py", line 1127, in write
    parser.write_row_stream(self.to_copy())
  File "/Users/mojmir/projects/etl/.venv/lib/python3.9/site-packages/frictionless/plugins/pandas/parser.py", line 179, in write_row_stream
    field["type"] == "integer"
KeyError: 'type'
```

The bug was [introduced in this PR](https://github.com/frictionlessdata/frictionless-py/commit/eea8ffb5bd30bc4d1c15dd981b4d4769f5f1e577#diff-f0b7ef231d4ca970a30bb6fb5ac537358697bcdfac4c676fabfef258fbf60dbfR179), perhaps it would be sufficient to change [this line](https://github.com/frictionlessdata/frictionless-py/blob/main/frictionless/plugins/pandas/parser.py#L179) to

```
field.get("type") == "integer"
```

Thanks!

Discussion:
shashigharti: @roll  @aivuk  It is ready for the review!

Patch:
diff --git a/frictionless/plugins/pandas/parser.py b/frictionless/plugins/pandas/parser.py
index 1cf2de22..cc3ee7da 100644
--- a/frictionless/plugins/pandas/parser.py
+++ b/frictionless/plugins/pandas/parser.py
@@ -176,11 +176,11 @@ class PandasParser(Parser):
         # Bug: #1109
         for field in source.schema.fields:
             if (
-                field["type"] == "integer"
-                and field["name"] in dataframe.columns
-                and str(dataframe.dtypes[field["name"]]) != "int64"
+                field.type == "integer"
+                and field.name in dataframe.columns
+                and str(dataframe.dtypes[field.name]) != "int64"
             ):
-                dataframe[field["name"]] = dataframe[field["name"]].astype("Int64")
+                dataframe[field.name] = dataframe[field.name].astype("Int64")
 
         target.data = dataframe
 


Test patch:
diff --git a/tests/plugins/pandas/test_parser.py b/tests/plugins/pandas/test_parser.py
index c402cfee..42730f36 100644
--- a/tests/plugins/pandas/test_parser.py
+++ b/tests/plugins/pandas/test_parser.py
@@ -74,6 +74,42 @@ def test_pandas_nan_in_integer_csv_column():
     assert all(df.dtypes.values == pd.array([pd.Int64Dtype(), float, object]))
 
 
+def test_pandas_nan_with_field_type_information_1143():
+    descriptor = {
+        "dialect": {"delimiter": ","},
+        "name": "issue-1109",
+        "path": "data/issue-1109.csv",
+        "schema": {
+            "fields": [
+                {"name": "int", "type": "integer"},
+                {"name": "number", "type": "number"},
+                {"name": "string", "type": "string"},
+            ]
+        },
+    }
+    res = Resource(descriptor)
+    df = res.to_pandas()
+    assert all(df.dtypes.values == pd.array([pd.Int64Dtype(), float, object]))
+
+
+def test_pandas_nan_without_field_type_information_1143():
+    descriptor = {
+        "dialect": {"delimiter": ","},
+        "name": "issue-1109",
+        "path": "data/issue-1109.csv",
+        "schema": {
+            "fields": [
+                {"name": "int"},
+                {"name": "number"},
+                {"name": "string"},
+            ]
+        },
+    }
+    res = Resource(descriptor)
+    df = res.to_pandas()
+    assert all(df.dtypes.values == pd.array([object, object, object]))
+
+
 def test_pandas_parser_write_types():
     source = Package("data/storage/types.json").get_resource("types")
     target = source.write(format="pandas")