barunsaha commited on
Commit
2985613
·
1 Parent(s): 5be3069

Update docstrings and imports

Browse files
src/slidedeckai/helpers/file_manager.py CHANGED
@@ -2,21 +2,18 @@
2
  File manager helper to work with uploaded files.
3
  """
4
  import logging
5
- import os
6
- import sys
7
 
8
  import streamlit as st
9
  from pypdf import PdfReader
10
 
11
- from ..global_config import GlobalConfig
12
-
13
 
14
  logger = logging.getLogger(__name__)
15
 
16
 
17
  def get_pdf_contents(
18
  pdf_file: st.runtime.uploaded_file_manager.UploadedFile,
19
- page_range: tuple[int, int]) -> str:
 
20
  """
21
  Extract the text contents from a PDF file.
22
 
 
2
  File manager helper to work with uploaded files.
3
  """
4
  import logging
 
 
5
 
6
  import streamlit as st
7
  from pypdf import PdfReader
8
 
 
 
9
 
10
  logger = logging.getLogger(__name__)
11
 
12
 
13
  def get_pdf_contents(
14
  pdf_file: st.runtime.uploaded_file_manager.UploadedFile,
15
+ page_range: tuple[int, int]
16
+ ) -> str:
17
  """
18
  Extract the text contents from a PDF file.
19
 
src/slidedeckai/helpers/image_search.py CHANGED
@@ -5,7 +5,7 @@ import logging
5
  import os
6
  import random
7
  from io import BytesIO
8
- from typing import Union, Tuple, Literal
9
  from urllib.parse import urlparse, parse_qs
10
 
11
  import requests
@@ -25,7 +25,6 @@ logging.getLogger('urllib3').setLevel(logging.ERROR)
25
  # logging.getLogger('urllib3').propagate = True
26
 
27
 
28
-
29
  def search_pexels(
30
  query: str,
31
  size: Literal['small', 'medium', 'large'] = 'medium',
@@ -45,13 +44,17 @@ def search_pexels(
45
  https://stackoverflow.com/a/51268523/147021
46
  https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox#linux
47
 
48
- :param query: The search query for finding images.
49
- :param size: The size of the images: small, medium, or large.
50
- :param per_page: No. of results to be displayed per page.
51
- :return: The JSON response from the Pexels API containing search results.
52
- :raises requests.exceptions.RequestException: If the request to the Pexels API fails.
53
- """
 
54
 
 
 
 
55
  url = 'https://api.pexels.com/v1/search'
56
  headers = {
57
  'Authorization': os.getenv('PEXEL_API_KEY'),
@@ -71,15 +74,17 @@ def search_pexels(
71
 
72
  def get_photo_url_from_api_response(
73
  json_response: dict
74
- ) -> Tuple[Union[str, None], Union[str, None]]:
75
  """
76
  Return a randomly chosen photo from a Pexels search API response. In addition, also return
77
  the original URL of the page on Pexels.
78
 
79
- :param json_response: The JSON response.
80
- :return: The selected photo URL and page URL or `None`.
81
- """
82
 
 
 
 
83
  page_url = None
84
  photo_url = None
85
 
@@ -109,11 +114,15 @@ def get_image_from_url(url: str) -> BytesIO:
109
  This function sends a GET request to the provided URL, retrieves the image data,
110
  and wraps it in a BytesIO object, which can be used like a file.
111
 
112
- :param url: The URL of the image to be fetched.
113
- :return: A BytesIO object containing the image data.
114
- :raises requests.exceptions.RequestException: If the request to the URL fails.
115
- """
 
116
 
 
 
 
117
  headers = {
118
  'Authorization': os.getenv('PEXEL_API_KEY'),
119
  'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20100101 Firefox/10.0',
@@ -125,12 +134,15 @@ def get_image_from_url(url: str) -> BytesIO:
125
  return image_data
126
 
127
 
128
- def extract_dimensions(url: str) -> Tuple[int, int]:
129
  """
130
  Extracts the height and width from the URL parameters.
131
 
132
- :param url: The URL containing the image dimensions.
133
- :return: A tuple containing the width and height as integers.
 
 
 
134
  """
135
  parsed_url = urlparse(url)
136
  query_params = parse_qs(parsed_url.query)
 
5
  import os
6
  import random
7
  from io import BytesIO
8
+ from typing import Union, Literal
9
  from urllib.parse import urlparse, parse_qs
10
 
11
  import requests
 
25
  # logging.getLogger('urllib3').propagate = True
26
 
27
 
 
28
  def search_pexels(
29
  query: str,
30
  size: Literal['small', 'medium', 'large'] = 'medium',
 
44
  https://stackoverflow.com/a/51268523/147021
45
  https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox#linux
46
 
47
+ Args:
48
+ query: The search query for finding images.
49
+ size: The size of the images: small, medium, or large.
50
+ per_page: No. of results to be displayed per page.
51
+
52
+ Returns:
53
+ The JSON response from the Pexels API containing search results.
54
 
55
+ Raises:
56
+ requests.exceptions.RequestException: If the request to the Pexels API fails.
57
+ """
58
  url = 'https://api.pexels.com/v1/search'
59
  headers = {
60
  'Authorization': os.getenv('PEXEL_API_KEY'),
 
74
 
75
  def get_photo_url_from_api_response(
76
  json_response: dict
77
+ ) -> tuple[Union[str, None], Union[str, None]]:
78
  """
79
  Return a randomly chosen photo from a Pexels search API response. In addition, also return
80
  the original URL of the page on Pexels.
81
 
82
+ Args:
83
+ json_response: The JSON response.
 
84
 
85
+ Returns:
86
+ The selected photo URL and page URL or `None`.
87
+ """
88
  page_url = None
89
  photo_url = None
90
 
 
114
  This function sends a GET request to the provided URL, retrieves the image data,
115
  and wraps it in a BytesIO object, which can be used like a file.
116
 
117
+ Args:
118
+ url: The URL of the image to be fetched.
119
+
120
+ Returns:
121
+ A BytesIO object containing the image data.
122
 
123
+ Raises:
124
+ requests.exceptions.RequestException: If the request to the URL fails.
125
+ """
126
  headers = {
127
  'Authorization': os.getenv('PEXEL_API_KEY'),
128
  'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20100101 Firefox/10.0',
 
134
  return image_data
135
 
136
 
137
+ def extract_dimensions(url: str) -> tuple[int, int]:
138
  """
139
  Extracts the height and width from the URL parameters.
140
 
141
+ Args:
142
+ url: The URL containing the image dimensions.
143
+
144
+ Returns:
145
+ A tuple containing the width and height as integers.
146
  """
147
  parsed_url = urlparse(url)
148
  query_params = parse_qs(parsed_url.query)
src/slidedeckai/helpers/pptx_helper.py CHANGED
@@ -6,9 +6,8 @@ import os
6
  import pathlib
7
  import random
8
  import re
9
- import sys
10
  import tempfile
11
- from typing import List, Tuple, Optional
12
 
13
  import json5
14
  import pptx
@@ -69,23 +68,26 @@ def remove_slide_number_from_heading(header: str) -> str:
69
  """
70
  Remove the slide number from a given slide header.
71
 
72
- :param header: The header of a slide.
73
- :return: The header without slide number.
74
- """
75
 
 
 
 
76
  if SLIDE_NUMBER_REGEX.match(header):
77
  idx = header.find(':')
78
- header = header[idx + 1:]
79
 
80
  return header
81
 
82
 
83
  def add_bulleted_items(text_frame: pptx.text.text.TextFrame, flat_items_list: list):
84
- """
85
- Add a list of texts as bullet points and apply formatting.
86
 
87
- :param text_frame: The text frame where text is to be displayed.
88
- :param flat_items_list: The list of items to be displayed.
 
 
89
  """
90
 
91
  for idx, an_item in enumerate(flat_items_list):
@@ -98,12 +100,14 @@ def add_bulleted_items(text_frame: pptx.text.text.TextFrame, flat_items_list: li
98
  format_text(paragraph, an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER))
99
 
100
 
101
- def format_text(frame_paragraph, text):
102
- """
103
- Apply bold and italic formatting while preserving the original word order
104
- without duplication.
105
  """
 
106
 
 
 
 
 
107
  matches = list(BOLD_ITALICS_PATTERN.finditer(text))
108
  last_index = 0 # Track position in the text
109
  # Group 0: Full match (e.g., **bold** or *italic*)
@@ -139,14 +143,17 @@ def generate_powerpoint_presentation(
139
  parsed_data: dict,
140
  slides_template: str,
141
  output_file_path: pathlib.Path
142
- ) -> List:
143
  """
144
- Create and save a PowerPoint presentation file containing the content in JSON format.
145
 
146
- :param parsed_data: The presentation content as parsed JSON data.
147
- :param slides_template: The PPTX template to use.
148
- :param output_file_path: The path of the PPTX file to save as.
149
- :return: A list of presentation title and slides headers.
 
 
 
150
  """
151
 
152
  presentation = pptx.Presentation(GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file'])
@@ -227,14 +234,17 @@ def generate_powerpoint_presentation(
227
  return all_headers
228
 
229
 
230
- def get_flat_list_of_contents(items: list, level: int) -> List[Tuple]:
231
  """
232
  Flatten a (hierarchical) list of bullet points to a single list containing each item and
233
- its level.
 
 
 
 
234
 
235
- :param items: A bullet point (string or list).
236
- :param level: The current level of hierarchy.
237
- :return: A list of (bullet item text, hierarchical level) tuples.
238
  """
239
 
240
  flat_list = []
@@ -252,24 +262,28 @@ def get_slide_placeholders(
252
  slide: pptx.slide.Slide,
253
  layout_number: int,
254
  is_debug: bool = False
255
- ) -> List[Tuple[int, str]]:
256
  """
257
- Return the index and name (lower case) of all placeholders present in a slide, except
258
- the title placeholder.
259
-
260
- A placeholder in a slide is a place to add content. Each placeholder has a name and an index.
261
- This index is NOT a list index, rather a set of keys used to look up a dict. So, `idx` is
262
- non-contiguous. Also, the title placeholder of a slide always has index 0. User-added
263
- placeholder get indices assigned starting from 10.
264
-
265
- With user-edited or added placeholders, their index may be difficult to track. This function
266
- returns the placeholders name as well, which could be useful to distinguish between the
267
- different placeholder.
268
-
269
- :param slide: The slide.
270
- :param layout_number: The layout number used by the slide.
271
- :param is_debug: Whether to print debugging statements.
272
- :return: A list containing placeholders (idx, name) tuples, except the title placeholder.
 
 
 
 
273
  """
274
 
275
  if is_debug:
@@ -298,10 +312,11 @@ def _handle_default_display(
298
  """
299
  Display a list of text in a slide.
300
 
301
- :param presentation: The presentation object.
302
- :param slide_json: The content of the slide as JSON data.
303
- :param slide_width_inch: The width of the slide in inches.
304
- :param slide_height_inch: The height of the slide in inches.
 
305
  """
306
 
307
  status = False
@@ -366,11 +381,14 @@ def _handle_display_image__in_foreground(
366
  Create a slide with text and image using a picture placeholder layout. If not image keyword is
367
  available, it will add only text to the slide.
368
 
369
- :param presentation: The presentation object.
370
- :param slide_json: The content of the slide as JSON data.
371
- :param slide_width_inch: The width of the slide in inches.
372
- :param slide_height_inch: The height of the slide in inches.
373
- :return: True if the side has been processed.
 
 
 
374
  """
375
 
376
  img_keywords = slide_json['img_keywords'].strip()
@@ -445,11 +463,14 @@ def _handle_display_image__in_background(
445
  `_handle_default_display()` but with a background image added. If not image keyword is
446
  available, it will add only text to the slide.
447
 
448
- :param presentation: The presentation object.
449
- :param slide_json: The content of the slide as JSON data.
450
- :param slide_width_inch: The width of the slide in inches.
451
- :param slide_height_inch: The height of the slide in inches.
452
- :return: True if the slide has been processed.
 
 
 
453
  """
454
 
455
  img_keywords = slide_json['img_keywords'].strip()
@@ -559,11 +580,14 @@ def _handle_icons_ideas(
559
  Add a slide with some icons and text.
560
  If no suitable icons are found, the step numbers are shown.
561
 
562
- :param presentation: The presentation object.
563
- :param slide_json: The content of the slide as JSON data.
564
- :param slide_width_inch: The width of the slide in inches.
565
- :param slide_height_inch: The height of the slide in inches.
566
- :return: True if the slide has been processed.
 
 
 
567
  """
568
 
569
  if 'bullet_points' in slide_json and slide_json['bullet_points']:
@@ -670,14 +694,15 @@ def _add_text_at_bottom(
670
  target_height: Optional[float] = 0.5
671
  ):
672
  """
673
- Add arbitrary text to a textbox positioned near the lower left side of a slide.
674
-
675
- :param slide: The slide.
676
- :param slide_width_inch: The width of the slide.
677
- :param slide_height_inch: The height of the slide.
678
- :param target_height: the target height of the box in inches (optional).
679
- :param text: The text to be added
680
- :param hyperlink: The hyperlink to be added to the text (optional).
 
681
  """
682
 
683
  footer = slide.shapes.add_textbox(
@@ -706,11 +731,14 @@ def _handle_double_col_layout(
706
  """
707
  Add a slide with a double column layout for comparison.
708
 
709
- :param presentation: The presentation object.
710
- :param slide_json: The content of the slide as JSON data.
711
- :param slide_width_inch: The width of the slide in inches.
712
- :param slide_height_inch: The height of the slide in inches.
713
- :return: True if double col layout has been added; False otherwise.
 
 
 
714
  """
715
 
716
  if 'bullet_points' in slide_json and slide_json['bullet_points']:
@@ -800,14 +828,16 @@ def _handle_step_by_step_process(
800
  slide_width_inch: float,
801
  slide_height_inch: float
802
  ) -> bool:
803
- """
804
- Add shapes to display a step-by-step process in the slide, if available.
 
 
 
 
 
805
 
806
- :param presentation: The presentation object.
807
- :param slide_json: The content of the slide as JSON data.
808
- :param slide_width_inch: The width of the slide in inches.
809
- :param slide_height_inch: The height of the slide in inches.
810
- :return True if this slide has a step-by-step process depiction added; False otherwise.
811
  """
812
 
813
  if 'bullet_points' in slide_json and slide_json['bullet_points']:
@@ -912,11 +942,14 @@ def _handle_table(
912
  """
913
  Add a table to a slide, if available.
914
 
915
- :param presentation: The presentation object.
916
- :param slide_json: The content of the slide as JSON data.
917
- :param slide_width_inch: The width of the slide in inches.
918
- :param slide_height_inch: The height of the slide in inches.
919
- :return True if this slide has a step-by-step process depiction added; False otherwise.
 
 
 
920
  """
921
 
922
  if 'table' not in slide_json or not slide_json['table']:
@@ -955,13 +988,17 @@ def _handle_key_message(
955
  slide_height_inch: float
956
  ):
957
  """
958
- Add a shape to display the key message in the slide, if available.
959
 
960
- :param the_slide: The slide to be processed.
961
- :param slide_json: The content of the slide as JSON data.
962
- :param slide_width_inch: The width of the slide in inches.
963
- :param slide_height_inch: The height of the slide in inches.
964
- """
 
 
 
 
965
 
966
  if 'key_message' in slide_json and slide_json['key_message']:
967
  height = pptx.util.Inches(1.6)
@@ -978,12 +1015,15 @@ def _handle_key_message(
978
  format_text(shape.text_frame.paragraphs[0], slide_json['key_message'])
979
 
980
 
981
- def _get_slide_width_height_inches(presentation: pptx.Presentation) -> Tuple[float, float]:
982
  """
983
  Get the dimensions of a slide in inches.
984
 
985
- :param presentation: The presentation object.
986
- :return: The width and the height.
 
 
 
987
  """
988
 
989
  slide_width_inch = EMU_TO_INCH_SCALING_FACTOR * presentation.slide_width
 
6
  import pathlib
7
  import random
8
  import re
 
9
  import tempfile
10
+ from typing import Optional
11
 
12
  import json5
13
  import pptx
 
68
  """
69
  Remove the slide number from a given slide header.
70
 
71
+ Args:
72
+ header: The header of a slide.
 
73
 
74
+ Returns:
75
+ str: The header without slide number.
76
+ """
77
  if SLIDE_NUMBER_REGEX.match(header):
78
  idx = header.find(':')
79
+ header = header[idx + 1:].strip()
80
 
81
  return header
82
 
83
 
84
  def add_bulleted_items(text_frame: pptx.text.text.TextFrame, flat_items_list: list):
85
+ """Add a list of texts as bullet points to a text frame and apply formatting.
 
86
 
87
+ Args:
88
+ text_frame (pptx.text.text.TextFrame): The text frame where text is to be
89
+ displayed.
90
+ flat_items_list (list): The list of items to be displayed.
91
  """
92
 
93
  for idx, an_item in enumerate(flat_items_list):
 
100
  format_text(paragraph, an_item[0].removeprefix(STEP_BY_STEP_PROCESS_MARKER))
101
 
102
 
103
+ def format_text(frame_paragraph, text: str):
 
 
 
104
  """
105
+ Apply bold and italic formatting while preserving the original word order without duplication.
106
 
107
+ Args:
108
+ frame_paragraph: The paragraph to format.
109
+ text: The text to format with markdown-style formatting.
110
+ """
111
  matches = list(BOLD_ITALICS_PATTERN.finditer(text))
112
  last_index = 0 # Track position in the text
113
  # Group 0: Full match (e.g., **bold** or *italic*)
 
143
  parsed_data: dict,
144
  slides_template: str,
145
  output_file_path: pathlib.Path
146
+ ) -> list:
147
  """
148
+ Create and save a PowerPoint presentation from parsed JSON content.
149
 
150
+ Args:
151
+ parsed_data (dict): The presentation content as parsed JSON data.
152
+ slides_template (str): The PPTX template key to use from GlobalConfig.
153
+ output_file_path (pathlib.Path): Destination path for the generated PPTX file.
154
+
155
+ Returns:
156
+ A list containing the presentation title and slide headers.
157
  """
158
 
159
  presentation = pptx.Presentation(GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file'])
 
234
  return all_headers
235
 
236
 
237
+ def get_flat_list_of_contents(items: list, level: int) -> list[tuple]:
238
  """
239
  Flatten a (hierarchical) list of bullet points to a single list containing each item and
240
+ its level.
241
+
242
+ Args:
243
+ items: A bullet point (string or list).
244
+ level: The current level of hierarchy.
245
 
246
+ Returns:
247
+ A list of (bullet item text, hierarchical level) tuples.
 
248
  """
249
 
250
  flat_list = []
 
262
  slide: pptx.slide.Slide,
263
  layout_number: int,
264
  is_debug: bool = False
265
+ ) -> list[tuple[int, str]]:
266
  """
267
+ Return the index and name (lower case) of all placeholders present in a
268
+ slide, except the title placeholder.
269
+
270
+ A placeholder in a slide is a place to add content. Each placeholder has a
271
+ name and an index. This index is not a list index; it is a key used to look up
272
+ a dict and may be non-contiguous. The title placeholder always has index 0.
273
+ User-added placeholders get indices starting from 10.
274
+
275
+ With user-edited or added placeholders, indices may be difficult to track. This
276
+ function returns the placeholders' names as well, which may help distinguish
277
+ between placeholders.
278
+
279
+ Args:
280
+ slide: The slide.
281
+ layout_number: The layout number used by the slide.
282
+ is_debug: Whether to print debugging statements.
283
+
284
+ Returns:
285
+ list[tuple[int, str]]: A list of (index, name) tuples for placeholders
286
+ present in the slide, excluding the title placeholder.
287
  """
288
 
289
  if is_debug:
 
312
  """
313
  Display a list of text in a slide.
314
 
315
+ Args:
316
+ presentation: The presentation object.
317
+ slide_json: The content of the slide as JSON data.
318
+ slide_width_inch: The width of the slide in inches.
319
+ slide_height_inch: The height of the slide in inches.
320
  """
321
 
322
  status = False
 
381
  Create a slide with text and image using a picture placeholder layout. If not image keyword is
382
  available, it will add only text to the slide.
383
 
384
+ Args:
385
+ presentation: The presentation object.
386
+ slide_json: The content of the slide as JSON data.
387
+ slide_width_inch: The width of the slide in inches.
388
+ slide_height_inch: The height of the slide in inches.
389
+
390
+ Returns:
391
+ bool: True if the side has been processed.
392
  """
393
 
394
  img_keywords = slide_json['img_keywords'].strip()
 
463
  `_handle_default_display()` but with a background image added. If not image keyword is
464
  available, it will add only text to the slide.
465
 
466
+ Args:
467
+ presentation: The presentation object.
468
+ slide_json: The content of the slide as JSON data.
469
+ slide_width_inch: The width of the slide in inches.
470
+ slide_height_inch: The height of the slide in inches.
471
+
472
+ Returns:
473
+ True if the slide has been processed.
474
  """
475
 
476
  img_keywords = slide_json['img_keywords'].strip()
 
580
  Add a slide with some icons and text.
581
  If no suitable icons are found, the step numbers are shown.
582
 
583
+ Args:
584
+ presentation: The presentation object.
585
+ slide_json: The content of the slide as JSON data.
586
+ slide_width_inch: The width of the slide in inches.
587
+ slide_height_inch: The height of the slide in inches.
588
+
589
+ Returns:
590
+ True if the slide has been processed.
591
  """
592
 
593
  if 'bullet_points' in slide_json and slide_json['bullet_points']:
 
694
  target_height: Optional[float] = 0.5
695
  ):
696
  """
697
+ Add arbitrary text to a textbox positioned near the lower-left side of a slide.
698
+
699
+ Args:
700
+ slide: The slide.
701
+ slide_width_inch: The width of the slide in inches.
702
+ slide_height_inch: The height of the slide in inches.
703
+ text: The text to be added.
704
+ hyperlink: Optional; the hyperlink to be added to the text.
705
+ target_height: Optional[float]; the target height of the box in inches.
706
  """
707
 
708
  footer = slide.shapes.add_textbox(
 
731
  """
732
  Add a slide with a double column layout for comparison.
733
 
734
+ Args:
735
+ presentation (pptx.Presentation): The presentation object.
736
+ slide_json (dict): The content of the slide as JSON data.
737
+ slide_width_inch (float): The width of the slide in inches.
738
+ slide_height_inch (float): The height of the slide in inches.
739
+
740
+ Returns:
741
+ bool: True if double col layout has been added; False otherwise.
742
  """
743
 
744
  if 'bullet_points' in slide_json and slide_json['bullet_points']:
 
828
  slide_width_inch: float,
829
  slide_height_inch: float
830
  ) -> bool:
831
+ """Add shapes to display a step-by-step process in the slide, if available.
832
+
833
+ Args:
834
+ presentation (pptx.Presentation): The presentation object.
835
+ slide_json (dict): The content of the slide as JSON data.
836
+ slide_width_inch (float): The width of the slide in inches.
837
+ slide_height_inch (float): The height of the slide in inches.
838
 
839
+ Returns:
840
+ bool: True if this slide has a step-by-step process depiction added; False otherwise.
 
 
 
841
  """
842
 
843
  if 'bullet_points' in slide_json and slide_json['bullet_points']:
 
942
  """
943
  Add a table to a slide, if available.
944
 
945
+ Args:
946
+ presentation (pptx.Presentation): The presentation object.
947
+ slide_json (dict): The content of the slide as JSON data.
948
+ slide_width_inch (float): The width of the slide in inches.
949
+ slide_height_inch (float): The height of the slide in inches.
950
+
951
+ Returns:
952
+ bool: True if a table was added to the slide; False otherwise.
953
  """
954
 
955
  if 'table' not in slide_json or not slide_json['table']:
 
988
  slide_height_inch: float
989
  ):
990
  """
991
+ Add a shape to display the key message in the slide, if available.
992
 
993
+ Args:
994
+ the_slide (pptx.slide.Slide): The slide to be processed.
995
+ slide_json (dict): The content of the slide as JSON data.
996
+ slide_width_inch (float): The width of the slide in inches.
997
+ slide_height_inch (float): The height of the slide in inches.
998
+
999
+ Returns:
1000
+ None
1001
+ """
1002
 
1003
  if 'key_message' in slide_json and slide_json['key_message']:
1004
  height = pptx.util.Inches(1.6)
 
1015
  format_text(shape.text_frame.paragraphs[0], slide_json['key_message'])
1016
 
1017
 
1018
+ def _get_slide_width_height_inches(presentation: pptx.Presentation) -> tuple[float, float]:
1019
  """
1020
  Get the dimensions of a slide in inches.
1021
 
1022
+ Args:
1023
+ presentation: The presentation object.
1024
+
1025
+ Returns:
1026
+ The width and the height.
1027
  """
1028
 
1029
  slide_width_inch = EMU_TO_INCH_SCALING_FACTOR * presentation.slide_width