Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

type annotations for csv.DictWriter

Tags:

python

mypy

I have trouble typo annotation csv.DictWriter. I am using mypy 0.910 and python 3.9.9.

def csv_bytes_from_dict_list(dict_list: List[Dict[str, Union[str, int]]]) -> bytes:
    with TextIOWrapper(BytesIO(), encoding="utf-8") as r:
        w = DictWriter(r, fieldnames=dict_list[0].keys(), quotechar='"', quoting=QUOTE_ALL)
        w.writeheader()
        w.writerows(dict_list)
        r.flush()
        r.buffer.seek(0)
        b = r.buffer.read()
    return b

Mypy is showing the below errors. I am not sure how to fix them.

test.py: note: In function "csv_bytes_from_dict_list":
test.py:10:13: error: Need type annotation for "w"  [var-annotated]
            w = DictWriter(r, fieldnames=dict_list[0].keys(), quotechar='"', quoting=QUOTE_ALL)
                ^
test.py:10:38: error: Argument "fieldnames" to "DictWriter" has incompatible type "KeysView[str]"; expected "Sequence[<nothing>]"  [arg-type]
            w = DictWriter(r, fieldnames=dict_list[0].keys(), quotechar='"', quoting=QUOTE_ALL)

When I do

w: DictWriter = ...

I get the following error

error: Missing type parameters for generic type "DictWriter"

When I do:

w: DictWriter[Dict[str, Union[str, int]]] = ...

I get the following error.

Argument 1 to "writerows" of "DictWriter" has incompatible type "List[Dict[str, Union[str, int]]]"; expected "Iterable[Mapping[Dict[str, Union[str, int]], Any]]" 

As for the list, the following doesn't help.

fieldnames=list(dict_list[0])

It shows

Argument 1 to "list" has incompatible type "Dict[str, Union[str, int]]"; expected "Iterable[Dict[str, Union[str, int]]]"  [arg-type]
                r, fieldnames=list(dict_list[0]), quotechar='"', quoting=QUOTE_ALL
like image 581
The Fool Avatar asked Oct 24 '25 09:10

The Fool


1 Answers

So by playing around with the typing of the DictWriter, I noticed that whatever type I stick in there will show as the expected type for the first type of the write rows method, essentially the key of the mapping.

For example

# if w is typed like this
w: DictWriter[Dict[str, Union[str, int]]
# the arguments for w.writerows expects this type
Iterable[Mapping[Dict[str, Union[str, int]], Any]]

# if the type for w is
w: DictWriter[dict]
# the expected type for w.writerows is 
Iterable[Mapping[Dict[Any, Any], Any]]

Based on that, I came to the conclusion that the type for the DictWriter should be the type of the keys in the mapping.

# only the type of the keys
w: DictWriter[str]
# now the expected type for w.writerows also makes sense
# althogh its showing 'Any' as second type. I am not sure how to impove that
Iterable[Mapping[str, Any]]

That combined with list(dict_list[0]) solves the typing errors.

w: DictWriter[str] = DictWriter(r, fieldnames=list(dict_list[0]), ...)
like image 110
The Fool Avatar answered Oct 26 '25 08:10

The Fool



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!