22
33import csv
44import io
5- from typing import TYPE_CHECKING , AsyncIterator , Literal , TypedDict , cast
5+ import json
6+ from typing import TYPE_CHECKING , AsyncIterator , Literal , TextIO , TypedDict , cast
67
78from typing_extensions import NotRequired , Required , Unpack , override
89
@@ -189,6 +190,32 @@ async def get_data(self, **kwargs: Unpack[GetDataKwargs]) -> DatasetItemsListPag
189190 # https://github.com/apify/apify-sdk-python/issues/140
190191 return await self ._resource_client .list_items (** kwargs )
191192
193+ async def write_to (self , content_type : Literal ['json' , 'csv' ], destination : TextIO ) -> None :
194+ """Exports the entire dataset into an arbitrary stream.
195+
196+ Args:
197+ content_type: Specifies the output format
198+ destination: The stream into which the dataset contents should be written
199+ """
200+ items : list [dict ] = []
201+ limit = 1000
202+ offset = 0
203+
204+ while True :
205+ list_items = await self ._resource_client .list_items (limit = limit , offset = offset )
206+ items .extend (list_items .items )
207+ if list_items .total <= offset + list_items .count :
208+ break
209+ offset += list_items .count
210+
211+ if content_type == 'csv' :
212+ writer = csv .writer (destination , quoting = csv .QUOTE_MINIMAL )
213+ writer .writerows ([items [0 ].keys (), * [item .values () for item in items ]])
214+ elif content_type == 'json' :
215+ json .dump (items , destination )
216+ else :
217+ raise ValueError (f'Unsupported content type: { content_type } ' )
218+
192219 async def export_to (self , ** kwargs : Unpack [ExportToKwargs ]) -> None :
193220 """Exports the entire dataset into a specified file stored under a key in a key-value store.
194221
@@ -206,30 +233,15 @@ async def export_to(self, **kwargs: Unpack[ExportToKwargs]) -> None:
206233 to_key_value_store_name = kwargs .get ('to_key_value_store_name' , None )
207234
208235 key_value_store = await KeyValueStore .open (id = to_key_value_store_id , name = to_key_value_store_name )
209- items : list [dict ] = []
210- limit = 1000
211- offset = 0
212236
213- while True :
214- list_items = await self ._resource_client .list_items (limit = limit , offset = offset )
215- items .extend (list_items .items )
216- if list_items .total <= offset + list_items .count :
217- break
218- offset += list_items .count
237+ output = io .StringIO ()
238+ await self .write_to (content_type , output )
219239
220240 if content_type == 'csv' :
221- content_type_full = 'text/csv'
222- output = io .StringIO ()
223- writer = csv .writer (output , quoting = csv .QUOTE_MINIMAL )
224- writer .writerows ([items [0 ].keys (), * [item .values () for item in items ]])
225- value = output .getvalue ()
226- return await key_value_store .set_value (key , value , content_type_full )
241+ await key_value_store .set_value (key , output .getvalue (), 'text/csv' )
227242
228243 if content_type == 'json' :
229- content_type_full = 'application/json'
230- return await key_value_store .set_value (key , items , content_type_full )
231-
232- raise ValueError (f'Unsupported content type: { content_type } ' )
244+ await key_value_store .set_value (key , output .getvalue (), 'application/json' )
233245
234246 async def get_info (self ) -> DatasetMetadata | None :
235247 """Get an object containing general information about the dataset."""
0 commit comments