deckbridge 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. {deckbridge-0.2.0 → deckbridge-0.3.0}/.bumpversion.cfg +1 -1
  2. deckbridge-0.3.0/CHANGELOG.md +47 -0
  3. {deckbridge-0.2.0 → deckbridge-0.3.0}/PKG-INFO +44 -2
  4. {deckbridge-0.2.0 → deckbridge-0.3.0}/conda_recipe/meta.yaml +1 -1
  5. {deckbridge-0.2.0 → deckbridge-0.3.0}/pyproject.toml +12 -1
  6. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/_version.py +1 -1
  7. deckbridge-0.3.0/src/deckbridge/backends/gslides_backend.py +24 -0
  8. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/backends/pptx_backend.py +5 -1
  9. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/blocks.py +1 -0
  10. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/deck.py +21 -1
  11. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/specs.py +6 -6
  12. deckbridge-0.3.0/src/deckbridge/renderers/common/context.py +94 -0
  13. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/legend_renderer.py +14 -26
  14. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/slot_renderer.py +4 -15
  15. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/style_resolver.py +13 -6
  16. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/text_renderer.py +23 -47
  17. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/chart_builder.py +15 -16
  18. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/chart_compiler.py +22 -23
  19. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/chart_embedder.py +1 -1
  20. deckbridge-0.3.0/src/deckbridge/renderers/gslides/renderer.py +129 -0
  21. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/sheets_writer.py +8 -20
  22. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/utils.py +26 -0
  23. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/chart_builder.py +45 -10
  24. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/chart_compiler.py +1 -5
  25. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/renderer.py +2 -4
  26. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/utils.py +17 -0
  27. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/PKG-INFO +44 -2
  28. deckbridge-0.2.0/CHANGELOG.md +0 -5
  29. deckbridge-0.2.0/src/deckbridge/backends/gslides_backend.py +0 -15
  30. deckbridge-0.2.0/src/deckbridge/renderers/common/context.py +0 -23
  31. deckbridge-0.2.0/src/deckbridge/renderers/gslides/renderer.py +0 -69
  32. {deckbridge-0.2.0 → deckbridge-0.3.0}/.coveragerc +0 -0
  33. {deckbridge-0.2.0 → deckbridge-0.3.0}/LICENSE +0 -0
  34. {deckbridge-0.2.0 → deckbridge-0.3.0}/MANIFEST.in +0 -0
  35. {deckbridge-0.2.0 → deckbridge-0.3.0}/Makefile +0 -0
  36. {deckbridge-0.2.0 → deckbridge-0.3.0}/README.md +0 -0
  37. {deckbridge-0.2.0 → deckbridge-0.3.0}/build_conda.sh +0 -0
  38. {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/api/deckbridge.getting_started.rst +0 -0
  39. {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/api/deckbridge.rst +0 -0
  40. {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/api/modules.rst +0 -0
  41. {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/conf.py +0 -0
  42. {deckbridge-0.2.0 → deckbridge-0.3.0}/environment.yml +0 -0
  43. {deckbridge-0.2.0 → deckbridge-0.3.0}/make_docs.sh +0 -0
  44. {deckbridge-0.2.0 → deckbridge-0.3.0}/requirements.txt +0 -0
  45. {deckbridge-0.2.0 → deckbridge-0.3.0}/setup.cfg +0 -0
  46. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/__init__.py +0 -0
  47. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/_git_version.py +0 -0
  48. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/__init__.py +0 -0
  49. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/drive_folders.py +0 -0
  50. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/google_auth.py +0 -0
  51. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/session.py +0 -0
  52. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/backends/__init__.py +0 -0
  53. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/backends/base.py +0 -0
  54. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/config.py +0 -0
  55. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/__init__.py +0 -0
  56. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/layouts/__init__.py +0 -0
  57. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/layouts/registry.py +0 -0
  58. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/__init__.py +0 -0
  59. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/__init__.py +0 -0
  60. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/axis_resolver.py +0 -0
  61. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/__init__.py +0 -0
  62. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/__init__.py +0 -0
  63. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/templates/__init__.py +0 -0
  64. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/templates/default.pptx +0 -0
  65. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/themes/__init__.py +0 -0
  66. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/themes/default.py +0 -0
  67. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/utils.py +0 -0
  68. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/SOURCES.txt +0 -0
  69. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/dependency_links.txt +0 -0
  70. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/requires.txt +0 -0
  71. {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/top_level.txt +0 -0
  72. {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/__init__.py +0 -0
  73. {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/conftest.py +0 -0
  74. {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/test_dependencies.py +0 -0
  75. {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/test_flake8.py +0 -0
  76. {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/test_getting_started.py +0 -0
  77. {deckbridge-0.2.0 → deckbridge-0.3.0}/versioneer.py +0 -0
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 0.2.0
2
+ current_version = 0.3.0
3
3
 
4
4
  [bumpversion:file:src/deckbridge/_version.py]
5
5
 
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0
4
+
5
+ ### What's Changed
6
+ * Restructure Title Slides by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/5
7
+ * Slot name mapping by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/6
8
+ * RenderContext class to streamline code by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/7
9
+ * Enable Theme text formatting by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/8
10
+ * Theme Chart Styling by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/9
11
+ * Multiple Series by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/10
12
+ * Clean up legend renderer by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/11
13
+ * Consistent value axis range by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/12
14
+
15
+ **Full Changelog**: https://github.com/josephcobb111/deckbridge/compare/v0.1.0...v0.2.0
16
+
17
+
18
+ ## 0.2.0
19
+
20
+ ### What's Changed
21
+ * Restructure Title Slides by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/5
22
+ * Slot name mapping by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/6
23
+ * RenderContext class to streamline code by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/7
24
+ * Enable Theme text formatting by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/8
25
+ * Theme Chart Styling by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/9
26
+ * Multiple Series by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/10
27
+ * Clean up legend renderer by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/11
28
+ * Consistent value axis range by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/12
29
+ * Release v0.2.0 by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/14
30
+
31
+ **Full Changelog**: https://github.com/josephcobb111/deckbridge/compare/v0.1.0...v0.2.0
32
+
33
+
34
+ ## 0.1.0
35
+
36
+ Initial release with proof-of-concept functionality.
37
+
38
+ ### What's Changed
39
+ * Skeleton functionality by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/1
40
+ * Revision Two Slide Presentation by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/2
41
+ * Create Chart Layout Registry by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/3
42
+ * Miscellaneous clean-up by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/4
43
+
44
+ ### New Contributors
45
+ * @josephcobb111 made their first contribution in https://github.com/josephcobb111/deckbridge/pull/1
46
+
47
+ **Full Changelog**: https://github.com/josephcobb111/deckbridge/commits/v0.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deckbridge
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Deck builder for analytics.
5
5
  Author-email: Joseph Cobb <josephxcobb@gmail.com>
6
6
  Project-URL: repository, https://github.com/josephcobb111/deckbridge
@@ -77,6 +77,48 @@ Consult the [Changelog](https://github.com/josephcobb111/deckbridge/build/html/c
77
77
 
78
78
  # Changelog
79
79
 
80
+ ## 0.3.0
81
+
82
+ ### What's Changed
83
+ * Restructure Title Slides by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/5
84
+ * Slot name mapping by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/6
85
+ * RenderContext class to streamline code by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/7
86
+ * Enable Theme text formatting by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/8
87
+ * Theme Chart Styling by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/9
88
+ * Multiple Series by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/10
89
+ * Clean up legend renderer by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/11
90
+ * Consistent value axis range by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/12
91
+
92
+ **Full Changelog**: https://github.com/josephcobb111/deckbridge/compare/v0.1.0...v0.2.0
93
+
94
+
95
+ ## 0.2.0
96
+
97
+ ### What's Changed
98
+ * Restructure Title Slides by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/5
99
+ * Slot name mapping by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/6
100
+ * RenderContext class to streamline code by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/7
101
+ * Enable Theme text formatting by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/8
102
+ * Theme Chart Styling by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/9
103
+ * Multiple Series by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/10
104
+ * Clean up legend renderer by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/11
105
+ * Consistent value axis range by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/12
106
+ * Release v0.2.0 by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/14
107
+
108
+ **Full Changelog**: https://github.com/josephcobb111/deckbridge/compare/v0.1.0...v0.2.0
109
+
110
+
80
111
  ## 0.1.0
81
112
 
82
- The initial setup of this project.
113
+ Initial release with proof-of-concept functionality.
114
+
115
+ ### What's Changed
116
+ * Skeleton functionality by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/1
117
+ * Revision Two Slide Presentation by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/2
118
+ * Create Chart Layout Registry by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/3
119
+ * Miscellaneous clean-up by @josephcobb111 in https://github.com/josephcobb111/deckbridge/pull/4
120
+
121
+ ### New Contributors
122
+ * @josephcobb111 made their first contribution in https://github.com/josephcobb111/deckbridge/pull/1
123
+
124
+ **Full Changelog**: https://github.com/josephcobb111/deckbridge/commits/v0.1.0
@@ -1,6 +1,6 @@
1
1
  package:
2
2
  name: deckbridge
3
- version: "0.2.0"
3
+ version: "0.3.0"
4
4
 
5
5
  source:
6
6
  path: ../
@@ -161,6 +161,7 @@ ignore = [
161
161
  "UP035", # `typing.x` is deprecated, use `x` instead.
162
162
  "UP006", # `typing.x` is deprecated, use `x` instead.
163
163
  "C901", # McCabe complexity
164
+ "D100", # Missing docstring in public module
164
165
  ]
165
166
 
166
167
  [tool.ruff.lint.per-file-ignores]
@@ -199,9 +200,19 @@ logging-format-style = "new"
199
200
  fail-under = 9.5
200
201
 
201
202
  [tool.pylint."messages control"]
202
- disable = ["unspecified-encoding", "logging-too-many-args", "logging-fstring-interpolation", "too-few-public-methods"]
203
+ disable = [
204
+ "unspecified-encoding",
205
+ "logging-too-many-args",
206
+ "logging-fstring-interpolation",
207
+ "too-few-public-methods",
208
+ "missing-module-docstring",
209
+ ]
203
210
  good-names = ["df", "f"]
204
211
 
205
212
  [tool.pylint.miscellaneous]
206
213
  # List of note tags to take in consideration, separated by a comma
207
214
  notes = ["FIXME", "XXX", "TODO"]
215
+
216
+ [tool.pylint.design]
217
+ max-args = 10
218
+ max-positional-arguments = 10
@@ -1,3 +1,3 @@
1
1
  """Package version."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.0"
@@ -0,0 +1,24 @@
1
+ from ..renderers.gslides.renderer import GSlidesRenderer
2
+ from .base import BaseBackend
3
+
4
+
5
+ class GSlidesBackend(BaseBackend):
6
+ def __init__(self, presentation_id, spreadsheet_id, slides_service, sheets_service, execute_requests=True):
7
+ self.presentation_id = presentation_id
8
+ self.spreadsheet_id = spreadsheet_id
9
+ self.slides_service = slides_service
10
+ self.sheets_service = sheets_service
11
+
12
+ self.renderer = GSlidesRenderer(
13
+ slides_service=slides_service,
14
+ sheets_service=sheets_service,
15
+ spreadsheet_id=spreadsheet_id,
16
+ presentation_id=presentation_id,
17
+ execute_requests=execute_requests,
18
+ )
19
+
20
+ def render(self, deck):
21
+ self.renderer.theme = deck.config.theme
22
+ self.renderer.layouts = deck.config.layouts
23
+
24
+ self.renderer.render(deck)
@@ -8,4 +8,8 @@ class PPTXBackend(BaseBackend):
8
8
  self.template_path = template_path
9
9
 
10
10
  def render(self, deck):
11
- PPTXRenderer(template_path=self.template_path).render(deck, self.output_path)
11
+ renderer = PPTXRenderer(template_path=self.template_path)
12
+ renderer.theme = deck.config.theme
13
+ renderer.layouts = deck.config.layouts
14
+
15
+ renderer.render(deck, self.output_path)
@@ -10,3 +10,4 @@ class ChartBlock:
10
10
  chart_subtitle: str = ""
11
11
  value_axis_title: str = ""
12
12
  category_axis_title: str = ""
13
+ style_overrides: dict | None = None
@@ -1,8 +1,28 @@
1
+ from deckbridge.layouts.registry import LAYOUTS
2
+ from deckbridge.themes.default import THEME
3
+
1
4
  from ..backends.base import BaseBackend
2
5
 
3
6
 
7
+ class DeckConfig:
8
+ def __init__(
9
+ self,
10
+ theme=None,
11
+ layouts=None,
12
+ pptx_template=None,
13
+ gslides_template=None,
14
+ ):
15
+
16
+ self.theme = theme or THEME
17
+ self.layouts = layouts or LAYOUTS
18
+
19
+ self.pptx_template = pptx_template
20
+ self.gslides_template = gslides_template
21
+
22
+
4
23
  class Deck:
5
- def __init__(self):
24
+ def __init__(self, *, config=None):
25
+ self.config = config or DeckConfig()
6
26
  self.slides = []
7
27
 
8
28
  def add_slide(
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import Dict
2
+ from typing import Dict, Optional
3
3
 
4
4
  import pandas as pd
5
5
 
@@ -18,12 +18,12 @@ class ChartSpec:
18
18
  data: pd.DataFrame,
19
19
  x: str,
20
20
  *,
21
- y: str = None,
22
- series: list[dict] = None,
23
- value_axis_range: tuple[float] = None,
24
- value_axis_tick_format: str = None,
21
+ y: Optional[str] = None,
22
+ series: Optional[list[dict]] = None,
23
+ value_axis_range: Optional[tuple[float, float]] = None,
24
+ value_axis_tick_format: Optional[str] = None,
25
25
  data_format: str = "wide",
26
- series_field: str = None,
26
+ series_field: Optional[str] = None,
27
27
  show_data_labels: bool = False,
28
28
  ):
29
29
  self.chart_type = chart_type
@@ -0,0 +1,94 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Optional
3
+
4
+
5
+ @dataclass
6
+ class RenderContext:
7
+ backend: str
8
+ layout_spec: object
9
+ theme: dict
10
+
11
+ # Optional renderer-specific fields
12
+ slide_obj: object = None
13
+ sheets_service: object = None
14
+ slides_service: object = None
15
+
16
+ presentation_id: str = None
17
+ spreadsheet_id: str = None
18
+ page_id: str = None
19
+
20
+ chart_compiler: object = None
21
+
22
+ # Request queues - sheets
23
+ create_sheet_requests: list = field(default_factory=list)
24
+ create_values_requests: list = field(default_factory=list)
25
+ format_values_requests: list = field(default_factory=list)
26
+ create_chart_requests: list = field(default_factory=list)
27
+
28
+ # Request queues - slides
29
+ embed_chart_requests: list = field(default_factory=list)
30
+ create_text_requests: list = field(default_factory=list)
31
+ create_legend_requests: list = field(default_factory=list)
32
+
33
+ def add_create_sheet_requests(self, requests):
34
+ if not requests:
35
+ return
36
+
37
+ if isinstance(requests, list):
38
+ self.create_sheet_requests.extend(requests)
39
+ else:
40
+ self.create_sheet_requests.append(requests)
41
+
42
+ def add_create_values_requests(self, requests):
43
+ if not requests:
44
+ return
45
+
46
+ if isinstance(requests, list):
47
+ self.create_values_requests.extend(requests)
48
+ else:
49
+ self.create_values_requests.append(requests)
50
+
51
+ def add_format_values_requests(self, requests):
52
+ if not requests:
53
+ return
54
+
55
+ if isinstance(requests, list):
56
+ self.format_values_requests.extend(requests)
57
+ else:
58
+ self.format_values_requests.append(requests)
59
+
60
+ def add_create_chart_requests(self, requests):
61
+ if not requests:
62
+ return
63
+
64
+ if isinstance(requests, list):
65
+ self.create_chart_requests.extend(requests)
66
+ else:
67
+ self.create_chart_requests.append(requests)
68
+
69
+ def add_embed_chart_requests(self, requests):
70
+ if not requests:
71
+ return
72
+
73
+ if isinstance(requests, list):
74
+ self.embed_chart_requests.extend(requests)
75
+ else:
76
+ self.embed_chart_requests.append(requests)
77
+
78
+ def add_create_text_requests(self, requests):
79
+ if not requests:
80
+ return
81
+
82
+ if isinstance(requests, list):
83
+ self.create_text_requests.extend(requests)
84
+ else:
85
+ self.create_text_requests.append(requests)
86
+
87
+ def add_create_legend_requests(self, requests):
88
+ if not requests:
89
+ return
90
+
91
+ if isinstance(requests, list):
92
+ self.create_legend_requests.extend(requests)
93
+ else:
94
+ self.create_legend_requests.append(requests)
@@ -94,11 +94,11 @@ def _render_color_legend_pptx(ctx, slot, legend):
94
94
  }
95
95
 
96
96
  render_text_slot(
97
- backend="pptx",
98
- slot_key=f"color_legend_text_{i}",
97
+ ctx=ctx,
99
98
  slot=text_slot,
100
99
  text=[{"text": _get_label(item), "style_key": "color_legend"}],
101
- slide_obj=ctx.slide_obj,
100
+ slot_key=f"color_legend_text_{i}",
101
+ style_overrides=None,
102
102
  )
103
103
 
104
104
 
@@ -163,20 +163,14 @@ def _render_color_legend_gslides(ctx, slot_key, slot, legend):
163
163
  }
164
164
 
165
165
  render_text_slot(
166
- backend="gslides",
167
- slot_key=f"{slot_key}_text_{i}",
166
+ ctx=ctx,
168
167
  slot=text_slot,
169
168
  text=[{"text": _get_label(item), "style_key": "color_legend"}],
170
- slides_service=ctx.slides_service,
171
- presentation_id=ctx.presentation_id,
172
- page_id=ctx.page_id,
169
+ slot_key=f"{slot_key}_text_{i}",
170
+ style_overrides=None,
173
171
  )
174
172
 
175
- if requests:
176
- ctx.slides_service.presentations().batchUpdate(
177
- presentationId=ctx.presentation_id,
178
- body={"requests": requests},
179
- ).execute()
173
+ ctx.add_create_legend_requests(requests)
180
174
 
181
175
 
182
176
  # =========================================================
@@ -234,11 +228,11 @@ def _render_dash_legend_pptx(ctx, slot, legend):
234
228
  }
235
229
 
236
230
  render_text_slot(
237
- backend="pptx",
238
- slot_key=f"dash_legend_text_{i}",
231
+ ctx=ctx,
239
232
  slot=text_slot,
240
233
  text=[{"text": label, "style_key": "dash_legend"}],
241
- slide_obj=ctx.slide_obj,
234
+ slot_key=f"dash_legend_text_{i}",
235
+ style_overrides=None,
242
236
  )
243
237
 
244
238
 
@@ -318,17 +312,11 @@ def _render_dash_legend_gslides(
318
312
  }
319
313
 
320
314
  render_text_slot(
321
- backend="gslides",
322
- slot_key=f"{slot_key}_text_{i}",
315
+ ctx=ctx,
323
316
  slot=text_slot,
324
317
  text=[{"text": label, "style_key": "dash_legend"}],
325
- slides_service=ctx.slides_service,
326
- presentation_id=ctx.presentation_id,
327
- page_id=ctx.page_id,
318
+ slot_key=f"{slot_key}_text_{i}",
319
+ style_overrides=None,
328
320
  )
329
321
 
330
- if requests:
331
- ctx.slides_service.presentations().batchUpdate(
332
- presentationId=ctx.presentation_id,
333
- body={"requests": requests},
334
- ).execute()
322
+ ctx.add_create_legend_requests(requests)
@@ -1,5 +1,3 @@
1
- from pptx.util import Inches
2
-
3
1
  from deckbridge.renderers.common.axis_resolver import resolve_shared_axis_ranges
4
2
  from deckbridge.renderers.common.legend_renderer import render_color_legend, render_dash_legend
5
3
  from deckbridge.renderers.common.text_renderer import render_text_slot, resolve_text_content
@@ -19,8 +17,8 @@ def render_slots(ctx, slide):
19
17
  _render_chart(ctx, slot, block, slot_key, slide)
20
18
 
21
19
  elif slot_type == "text":
22
- text = resolve_text_content(slide, slot_key, slot)
23
- _render_text(ctx, slot, text, slot_key)
20
+ text, style_overrides = resolve_text_content(slide, slot_key, slot)
21
+ _render_text(ctx, slot, text, slot_key, style_overrides)
24
22
 
25
23
  elif slot_type == "color_legend":
26
24
  render_color_legend(ctx, slot_key, slot, slide)
@@ -37,14 +35,5 @@ def _render_chart(ctx, slot, block, slot_key, slide):
37
35
  ctx.chart_compiler.compile(ctx, slot, block, slot_key, shared_axis)
38
36
 
39
37
 
40
- def _render_text(ctx, slot, text, slot_key):
41
- render_text_slot(
42
- backend=ctx.backend,
43
- slot_key=slot_key,
44
- slot=slot,
45
- text=text,
46
- slide_obj=ctx.slide_obj,
47
- slides_service=ctx.slides_service,
48
- presentation_id=ctx.presentation_id,
49
- page_id=ctx.page_id,
50
- )
38
+ def _render_text(ctx, slot, text, slot_key, style_overrides=None):
39
+ render_text_slot(ctx, slot, text, slot_key, style_overrides)
@@ -1,15 +1,19 @@
1
- from deckbridge.themes.default import DEFAULT_TEXT_STYLE, THEME
1
+ from deckbridge.themes.default import DEFAULT_TEXT_STYLE
2
2
  from deckbridge.utils import deep_merge
3
3
 
4
4
 
5
- def resolve_chart_theme(theme, layout_name):
5
+ def resolve_chart_theme(theme, layout_name, style_overrides=None):
6
6
  base = theme.get("chart", {}).get("default", {})
7
7
  layout_override = theme.get("chart", {}).get("layouts", {}).get(layout_name, {})
8
8
 
9
- return deep_merge(base, layout_override)
9
+ resolved = deep_merge(base, layout_override)
10
+ if style_overrides:
11
+ resolved = deep_merge(resolved, style_overrides)
10
12
 
13
+ return resolved
11
14
 
12
- def resolve_text_style(slot_key, slot):
15
+
16
+ def resolve_text_style(slot_key, slot, theme, layout_name, style_overrides):
13
17
  """
14
18
  Merge style layers:
15
19
  DEFAULT → THEME (global) → THEME (slot) → slot
@@ -17,10 +21,13 @@ def resolve_text_style(slot_key, slot):
17
21
 
18
22
  slot_group = slot.get("style_key", slot_key)
19
23
 
24
+ chart_theme = resolve_chart_theme(theme, layout_name, style_overrides) if "chart" in slot_key else {}
25
+
20
26
  style = {
21
27
  **DEFAULT_TEXT_STYLE,
22
- **THEME.get("text", {}),
23
- **THEME.get("slots", {}).get(slot_group, {}),
28
+ **theme.get("text", {}),
29
+ **theme.get("slots", {}).get(slot_group, {}),
30
+ **chart_theme.get(slot_group, {}),
24
31
  **slot,
25
32
  }
26
33
 
@@ -3,6 +3,7 @@ from pptx.util import Inches, Pt
3
3
  from deckbridge.renderers.common.style_resolver import resolve_text_style
4
4
  from deckbridge.renderers.gslides.utils import GSLIDES_ALIGN_MAP, GSLIDES_VERTICAL_ALIGN_MAP, hex_to_slides_rgb, inches_to_emu
5
5
  from deckbridge.renderers.pptx.utils import PPTX_ALIGN_MAP, PPTX_VERTICAL_ALIGN_MAP, hex_to_rgb255
6
+ from deckbridge.themes.default import THEME
6
7
 
7
8
 
8
9
  def resolve_text_content(slide, slot_key, slot):
@@ -11,7 +12,9 @@ def resolve_text_content(slide, slot_key, slot):
11
12
  if content_type == "chart_title":
12
13
  block = slide["content"].get(slot["source"])
13
14
  if not block:
14
- return None
15
+ return None, None
16
+
17
+ style_overrides = block.style_overrides
15
18
 
16
19
  title = block.chart_title
17
20
  subtitle = getattr(block, "chart_subtitle", None)
@@ -34,44 +37,27 @@ def resolve_text_content(slide, slot_key, slot):
34
37
  }
35
38
  )
36
39
 
37
- return lines if lines else None
40
+ return (lines, style_overrides) if lines else (None, None)
38
41
 
39
- return slide.get(slot_key)
42
+ return slide.get(slot_key), None
40
43
 
41
44
 
42
- def render_text_slot(
43
- backend,
44
- slot_key,
45
- slot,
46
- text,
47
- *,
48
- slide_obj=None,
49
- slides_service=None,
50
- presentation_id=None,
51
- page_id=None,
52
- ):
45
+ def render_text_slot(ctx, slot, text, slot_key, style_overrides):
53
46
  if not text:
54
47
  return
55
48
 
56
- if backend == "pptx":
57
- _render_text_pptx(slide_obj, slot_key, slot, text)
58
-
59
- elif backend == "gslides":
60
- _render_text_gslides(
61
- slides_service,
62
- presentation_id,
63
- page_id,
64
- slot_key,
65
- slot,
66
- text,
67
- )
49
+ if ctx.backend == "pptx":
50
+ _render_text_pptx(ctx, slot, text, slot_key, style_overrides)
51
+
52
+ elif ctx.backend == "gslides":
53
+ _render_text_gslides(ctx, slot, text, slot_key, style_overrides)
68
54
 
69
55
  else:
70
- raise ValueError(f"Unsupported backend: {backend}")
56
+ raise ValueError(f"Unsupported backend: {ctx.backend}")
71
57
 
72
58
 
73
- def _render_text_pptx(slide, slot_key, slot, text):
74
- textbox = slide.shapes.add_textbox(
59
+ def _render_text_pptx(ctx, slot, text, slot_key, style_overrides):
60
+ textbox = ctx.slide_obj.shapes.add_textbox(
75
61
  Inches(slot["x"]),
76
62
  Inches(slot["y"]),
77
63
  Inches(slot["w"]),
@@ -81,7 +67,7 @@ def _render_text_pptx(slide, slot_key, slot, text):
81
67
  tf = textbox.text_frame
82
68
  tf.clear()
83
69
 
84
- base_style = resolve_text_style(slot_key, slot)
70
+ base_style = resolve_text_style(slot_key, slot, ctx.theme, ctx.layout_spec.name, style_overrides)
85
71
  tf.vertical_anchor = PPTX_VERTICAL_ALIGN_MAP[base_style.get("vertical_align", "TOP")]
86
72
 
87
73
  p = tf.paragraphs[0]
@@ -92,7 +78,7 @@ def _render_text_pptx(slide, slot_key, slot, text):
92
78
  run = p.add_run()
93
79
  run.text = line["text"]
94
80
 
95
- style = resolve_text_style(line["style_key"], {"style_key": line["style_key"]})
81
+ style = resolve_text_style(line["style_key"], {"style_key": line["style_key"]}, ctx.theme, ctx.layout_spec.name, style_overrides)
96
82
 
97
83
  run.font.size = Pt(style["font_size"])
98
84
  run.font.bold = style["bold"]
@@ -104,15 +90,8 @@ def _render_text_pptx(slide, slot_key, slot, text):
104
90
  p.alignment = PPTX_ALIGN_MAP[base_style["align"]]
105
91
 
106
92
 
107
- def _render_text_gslides(
108
- slides_service,
109
- presentation_id,
110
- page_id,
111
- slot_key,
112
- slot,
113
- text,
114
- ):
115
- object_id = f"{slot_key}_{page_id}"
93
+ def _render_text_gslides(ctx, slot, text, slot_key, style_overrides):
94
+ object_id = f"{slot_key}_{ctx.page_id}"
116
95
 
117
96
  requests = []
118
97
 
@@ -144,7 +123,7 @@ def _render_text_gslides(
144
123
  "objectId": object_id,
145
124
  "shapeType": "TEXT_BOX",
146
125
  "elementProperties": {
147
- "pageObjectId": page_id,
126
+ "pageObjectId": ctx.page_id,
148
127
  "size": {
149
128
  "height": {"magnitude": inches_to_emu(slot["h"]), "unit": "EMU"},
150
129
  "width": {"magnitude": inches_to_emu(slot["w"]), "unit": "EMU"},
@@ -177,7 +156,7 @@ def _render_text_gslides(
177
156
  # Apply styles per range
178
157
  # -----------------------
179
158
  for start, end, style_key in ranges:
180
- style = resolve_text_style(style_key, {"style_key": style_key})
159
+ style = resolve_text_style(style_key, {"style_key": style_key}, ctx.theme, ctx.layout_spec.name, style_overrides)
181
160
 
182
161
  api_style = {
183
162
  "fontSize": {"magnitude": style["font_size"], "unit": "PT"},
@@ -205,7 +184,7 @@ def _render_text_gslides(
205
184
  # -----------------------
206
185
  # Alignment (whole paragraph)
207
186
  # -----------------------
208
- base_style = resolve_text_style(slot_key, slot)
187
+ base_style = resolve_text_style(slot_key, slot, ctx.theme, ctx.layout_spec.name, style_overrides)
209
188
 
210
189
  requests.append(
211
190
  {
@@ -232,7 +211,4 @@ def _render_text_gslides(
232
211
  }
233
212
  )
234
213
 
235
- slides_service.presentations().batchUpdate(
236
- presentationId=presentation_id,
237
- body={"requests": requests},
238
- ).execute()
214
+ ctx.add_create_text_requests(requests)