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.
- {deckbridge-0.2.0 → deckbridge-0.3.0}/.bumpversion.cfg +1 -1
- deckbridge-0.3.0/CHANGELOG.md +47 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/PKG-INFO +44 -2
- {deckbridge-0.2.0 → deckbridge-0.3.0}/conda_recipe/meta.yaml +1 -1
- {deckbridge-0.2.0 → deckbridge-0.3.0}/pyproject.toml +12 -1
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/_version.py +1 -1
- deckbridge-0.3.0/src/deckbridge/backends/gslides_backend.py +24 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/backends/pptx_backend.py +5 -1
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/blocks.py +1 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/deck.py +21 -1
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/specs.py +6 -6
- deckbridge-0.3.0/src/deckbridge/renderers/common/context.py +94 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/legend_renderer.py +14 -26
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/slot_renderer.py +4 -15
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/style_resolver.py +13 -6
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/text_renderer.py +23 -47
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/chart_builder.py +15 -16
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/chart_compiler.py +22 -23
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/chart_embedder.py +1 -1
- deckbridge-0.3.0/src/deckbridge/renderers/gslides/renderer.py +129 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/sheets_writer.py +8 -20
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/utils.py +26 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/chart_builder.py +45 -10
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/chart_compiler.py +1 -5
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/renderer.py +2 -4
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/utils.py +17 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/PKG-INFO +44 -2
- deckbridge-0.2.0/CHANGELOG.md +0 -5
- deckbridge-0.2.0/src/deckbridge/backends/gslides_backend.py +0 -15
- deckbridge-0.2.0/src/deckbridge/renderers/common/context.py +0 -23
- deckbridge-0.2.0/src/deckbridge/renderers/gslides/renderer.py +0 -69
- {deckbridge-0.2.0 → deckbridge-0.3.0}/.coveragerc +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/LICENSE +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/MANIFEST.in +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/Makefile +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/README.md +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/build_conda.sh +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/api/deckbridge.getting_started.rst +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/api/deckbridge.rst +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/api/modules.rst +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/docs/source/conf.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/environment.yml +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/make_docs.sh +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/requirements.txt +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/setup.cfg +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/_git_version.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/drive_folders.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/google_auth.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/auth/session.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/backends/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/backends/base.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/config.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/deck/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/layouts/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/layouts/registry.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/common/axis_resolver.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/gslides/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/renderers/pptx/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/templates/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/templates/default.pptx +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/themes/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/themes/default.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge/utils.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/SOURCES.txt +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/dependency_links.txt +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/requires.txt +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/src/deckbridge.egg-info/top_level.txt +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/__init__.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/conftest.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/test_dependencies.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/test_flake8.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/tests/test_getting_started.py +0 -0
- {deckbridge-0.2.0 → deckbridge-0.3.0}/versioneer.py +0 -0
|
@@ -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.
|
|
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
|
-
|
|
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
|
|
@@ -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 = [
|
|
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
|
|
@@ -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)
|
|
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)
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
page_id=ctx.page_id,
|
|
169
|
+
slot_key=f"{slot_key}_text_{i}",
|
|
170
|
+
style_overrides=None,
|
|
173
171
|
)
|
|
174
172
|
|
|
175
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
page_id=ctx.page_id,
|
|
318
|
+
slot_key=f"{slot_key}_text_{i}",
|
|
319
|
+
style_overrides=None,
|
|
328
320
|
)
|
|
329
321
|
|
|
330
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
23
|
-
**
|
|
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(
|
|
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(
|
|
74
|
-
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
|
-
|
|
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
|
-
|
|
236
|
-
presentationId=presentation_id,
|
|
237
|
-
body={"requests": requests},
|
|
238
|
-
).execute()
|
|
214
|
+
ctx.add_create_text_requests(requests)
|