11"""Access Datawrapper's API to create, update, delete charts.
22
33Datawrapper API lets you programatically interface with your charts.
4- It lets you create and edit charts, update your account information and many more things to come.
4+ It lets you create and edit charts, update your account information and many more things
5+ to come.
56
67 This package is a light-weight wrapper around Datawrapper's API.
78
3132class Datawrapper :
3233 """Handles connecting with Datawrapper's API.
3334
34- Handles access to your Datawrapper's account, create, delete and move charts, tables or maps.
35+ Handles access to your Datawrapper's account, create, delete and move charts, tables
36+ or maps.
3537 Will attempt to read environment variable DATAWRAPPER_ACCESS_TOKEN by default.
3638
3739 Args:
38- access_token: A personal access token to use the API. See app.datawrapper.de/account/api-tokens.
40+ access_token: A personal access token to use the API.
41+ See app.datawrapper.de/account/api-tokens.
3942 """
4043
4144 _BASE_URL = "https://api.datawrapper.de"
@@ -73,7 +76,10 @@ def account_info(self) -> dict[Any, Any] | None | Any:
7376 if account_info_response .status_code == 200 :
7477 return account_info_response .json ()
7578 else :
76- msg = "Couldn't find account. Make sure your credentials (access_code) are correct."
79+ msg = (
80+ "Couldn't find account. Make sure your credentials " ,
81+ "(access_code) are correct." ,
82+ )
7783 logger .error (msg )
7884 raise Exception (msg )
7985
@@ -85,7 +91,8 @@ def add_data(self, chart_id: str, data: pd.DataFrame | str) -> r.Response:
8591 chart_id : str
8692 ID of chart, table or map to add data to.
8793 data : pd.DataFrame | str
88- A pandas dataframe containing the data to be added or a string that contains the data.
94+ A pandas dataframe containing the data to be added or a string that contains
95+ the data.
8996
9097 Returns
9198 -------
@@ -151,13 +158,17 @@ def create_chart(
151158 title : str, optional
152159 Title for new chart, table or map, by default "New Chart"
153160 chart_type : str, optional
154- Chart type to be created. See https://developer.datawrapper.de/docs/chart-types, by default "d3-bars-stacked"
161+ Chart type to be created. See https://developer.datawrapper.de/docs/chart-types,
162+ by default "d3-bars-stacked"
155163 data : [type], optional
156- A pandas DataFrame or string containing the data to be added, by default None
164+ A pandas DataFrame or string containing the data to be added,
165+ by default None
157166 folder_id : str, optional
158- ID of folder in Datawrapper.de for the chart, table or map to be created in, by default ""
167+ ID of folder in Datawrapper.de for the chart, table or map to be created in,
168+ by default ""
159169 organization_id : str, optional
160- ID of the team where the chart should be created. The authenticated user must have access to this team.
170+ ID of the team where the chart should be created. The authenticated user
171+ must have access to this team.
161172 metadata: dict, optional
162173 A Python dictionary of properties to add.
163174
@@ -192,7 +203,10 @@ def create_chart(
192203 "\n NOTE: Maps need a valid basemap, set in properties -> visualize"
193204 )
194205 logger .debug (
195- "Full list of valid maps can be retrieved with\n \n curl --request GET --url https://api.datawrapper.de/plugin/basemap\n "
206+ (
207+ "Full list of valid maps can be retrieved with\n \n " ,
208+ "curl --request GET --url https://api.datawrapper.de/plugin/basemap\n " ,
209+ )
196210 )
197211
198212 if new_chart_response .status_code <= 201 :
@@ -299,8 +313,6 @@ def publish_chart(self, chart_id: str, display: bool = True) -> Any | None:
299313 iframe_code = publish_chart_info ["data" ]["metadata" ]["publish" ][
300314 "embed-codes"
301315 ]["embed-method-iframe" ]
302- # iframe_width = publish_chart_info['data']['metadata']['publish']['embed-width']
303- # iframe_height = publish_chart_info['data']['metadata']['publish']['embed-height']
304316 return HTML (iframe_code )
305317 else :
306318 return None
@@ -331,12 +343,17 @@ def chart_properties(
331343 if chart_properties_response .status_code == 200 :
332344 return chart_properties_response .json ()
333345 else :
334- msg = "Make sure you have the right id and authorization credentials (access_token)."
346+ msg = (
347+ "Make sure you have the right id and authorization " ,
348+ "credentials (access_token)." ,
349+ )
335350 logger .error (msg )
336351 raise Exception (msg )
337352
338353 def chart_data (self , chart_id : str ):
339- """Retrieve the data stored for a specific chart, table or map, which is typically CSV.
354+ """Retrieve the data stored for a specific chart, table or map,
355+ which is typically CSV.
356+
340357
341358 Parameters
342359 ----------
@@ -357,7 +374,7 @@ def chart_data(self, chart_id: str):
357374 # Check if the request was successful
358375 assert (
359376 response .ok
360- ), "Make sure you have the right id and authorization credentials (access_token)."
377+ ), "Ensure you have the right id and authorization credentials (access_token)."
361378
362379 # Return the data as json if the mimetype is json
363380 if "json" in response .headers ["content-type" ]:
@@ -411,7 +428,9 @@ def update_chart(
411428 folder_id : str = "" ,
412429 organization_id : str = "" ,
413430 ) -> Any | None :
414- """Updates a chart's title, theme, type, language, or location (folder/organization).
431+ """Updates a chart's title, theme, type, language,
432+ or location (folder/organization).
433+
415434
416435 Parameters
417436 ----------
@@ -422,7 +441,8 @@ def update_chart(
422441 theme : str, optional
423442 New theme, by default ""
424443 chart_type : str, optional
425- New chart type. See https://developer.datawrapper.de/docs/chart-types, by default ""
444+ New chart type. See https://developer.datawrapper.de/docs/chart-types,
445+ by default ""
426446 language : str, optional
427447 New language, by default ""
428448 folder_id : str, optional
@@ -529,13 +549,17 @@ def export_chart(
529549 chart_id : str
530550 ID of chart, table, or map.
531551 unit : str, optional
532- One of px, mm, inch. Defines the unit in which the borderwidth, height, and width will be measured in, by default "px"
552+ One of px, mm, inch. Defines the unit in which the borderwidth, height,
553+ and width will be measured in, by default "px"
533554 mode : str, optional
534- One of rgb or cmyk. Which color mode the output should be in, by default "rgb"
555+ One of rgb or cmyk. Which color mode the output should be in,
556+ by default "rgb"
535557 width : int, optional
536- Width of visualization. If not specified, it takes the chart width, by default None
558+ Width of visualization. If not specified, it takes the chart width,
559+ by default None
537560 plain : bool, optional
538- Defines if only the visualization should be exported (True), or if it should include header and footer as well (False), by default False
561+ Defines if only the visualization should be exported (True), or if it should
562+ include header and footer as well (False), by default False
539563 zoom : int, optional
540564 Defines the multiplier for the png size, by default 2
541565 scale : int, optional
@@ -549,7 +573,8 @@ def export_chart(
549573 filepath : str, optional
550574 Name/filepath to save output in, by default "./image.png"
551575 display : bool, optional
552- Whether to display the exported image as output in the notebook cell, by default False
576+ Whether to display the exported image as output in the notebook cell,
577+ by default False
553578
554579 Returns None
555580 -------
@@ -606,7 +631,8 @@ def get_folders(self) -> dict[Any, Any] | None | Any:
606631 Returns
607632 -------
608633 dict
609- A dictionary containing the folders in your Datawrapper account and their information.
634+ A dictionary containing the folders in your Datawrapper account and their
635+ information.
610636 """
611637 get_folders_response = r .get (
612638 url = self ._FOLDERS_URL ,
@@ -616,7 +642,10 @@ def get_folders(self) -> dict[Any, Any] | None | Any:
616642 if get_folders_response .status_code == 200 :
617643 return get_folders_response .json ()
618644 else :
619- msg = "Couldn't retrieve folders in account. Make sure you have the rigth authorization credentials (access token)."
645+ msg = (
646+ "Couldn't retrieve folders in account. Make sure you have the right " ,
647+ "authorization credentials (access token)." ,
648+ )
620649 logger .error (msg )
621650 raise Exception (msg )
622651
@@ -654,7 +683,7 @@ def create_folder(
654683 self ,
655684 name : str ,
656685 parent_id : str | int | None = None ,
657- team_id : str | int | None = None
686+ team_id : str | int | None = None ,
658687 ) -> dict [Any , Any ]:
659688 """Create a new folder.
660689
@@ -665,7 +694,8 @@ def create_folder(
665694 parent_id: str | int, optional
666695 The parent folder that the folder belongs to.
667696 team_id: str | int, optional
668- The team that the folder belongs to. If teamId is empty, the folder will belong to the user directly.
697+ The team that the folder belongs to. If teamId is empty, the folder will
698+ belong to the user directly.
669699
670700 Returns
671701 -------
@@ -689,7 +719,9 @@ def create_folder(
689719
690720 if response .ok :
691721 folder_info = response .json ()
692- logger .debug (f"Folder { folder_info ['name' ]} created with id { folder_info ['id' ]} " )
722+ logger .debug (
723+ f"Folder { folder_info ['name' ]} created with id { folder_info ['id' ]} "
724+ )
693725 return folder_info
694726 else :
695727 msg = "Folder could not be created."
@@ -830,21 +862,18 @@ def copy_chart(self, chart_id: str) -> dict[Any, Any]:
830862 _header ["accept" ] = "*/*"
831863
832864 url = f"{ self ._CHARTS_URL } /{ chart_id } /copy"
833- response = r .post (
834- url = url ,
835- headers = _header
836- )
865+ response = r .post (url = url , headers = _header )
837866
838867 if response .ok :
839868 copy_id = response .json ()
840- logger .debug (f"Chart { chart_id } copied to { copy_id } " )
869+ logger .debug (f"Chart { chart_id } copied to { copy_id [ 'id' ] } " )
841870 return copy_id
842871 else :
843872 msg = "Chart could not be copied at the moment."
844873 logger .error (msg )
845874 raise Exception (msg )
846875
847- def fork_chart (self , chart_id : str ) -> str :
876+ def fork_chart (self , chart_id : str ) -> dict [ Any , Any ] :
848877 """Fork a chart, table, or map and create an editable copy.
849878
850879 Parameters
@@ -861,17 +890,17 @@ def fork_chart(self, chart_id: str) -> str:
861890 _header ["accept" ] = "*/*"
862891
863892 url = f"{ self ._CHARTS_URL } /{ chart_id } /fork"
864- response = r .post (
865- url = url ,
866- headers = _header
867- )
893+ response = r .post (url = url , headers = _header )
868894
869895 if response .ok :
870- fork_id = response .json ()[ "id" ]
871- logger .debug (f"Chart { chart_id } copied to { fork_id } " )
872- return fork_id
896+ fork = response .json ()
897+ logger .debug (f"Chart { chart_id } copied to { fork [ 'id' ] } " )
898+ return fork
873899 else :
874- msg = "Chart could not be forked. If it's a chart you created, you should trying copying it instead."
900+ msg = (
901+ "Chart could not be forked. If it's a chart you created, " ,
902+ "you should trying copying it instead." ,
903+ )
875904 logger .error (msg )
876905 raise Exception (msg )
877906
@@ -922,13 +951,15 @@ def get_charts(
922951 order : str, optional
923952 Result order (ascending or descending), by default "DESC"
924953 order_by : str, optional
925- Attribute to order by. One of createdAt, email, id, or name, by default "createdAt"
954+ Attribute to order by. One of createdAt, email, id, or name,
955+ by default "createdAt"
926956 limit : int, optional
927957 Maximum items to fetch, by default 25
928958 folder_id : str, optional
929959 ID of folder in Datawrapper.de where to list charts, by default ""
930960 team_id : str, optional
931- ID of the team where to list charts. The authenticated user must have access to this team, by default ""
961+ ID of the team where to list charts. The authenticated user must have access
962+ to this team, by default ""
932963
933964 Returns
934965 -------
0 commit comments