athena-python-pptx 0.3.0__tar.gz → 0.4.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.
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/CHANGELOG.md +41 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/PKG-INFO +1 -1
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/docs/API_PARITY_EXCEPTIONS.md +61 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/__init__.py +1 -1
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/client.py +25 -12
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/commands.py +17 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/__init__.py +626 -16
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/slides.py +96 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pyproject.toml +1 -1
- athena_python_pptx-0.4.0/uv.lock +1163 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/.gitignore +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/API_PARITY_REPORT.md +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/CLAUDE.md +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/DEV-GUIDE.md +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/PARITY_QUESTIONS.md +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/PUBLISHING.md +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/README.md +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/docs/athena-api.json +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/docs/athena-api.md +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/_athena_extension.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/_ptc.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/_references.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/action.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/batching.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/__init__.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/axis.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/category.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/chart.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/data.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/datalabel.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/legend.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/marker.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/plot.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/point.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/series.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/chart/xlsx.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/decorators.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/dml/__init__.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/dml/chtfmt.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/dml/color.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/dml/effect.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/dml/fill.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/dml/line.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/docgen.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/enum/__init__.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/enum/action.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/enum/chart.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/enum/dml.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/enum/lang.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/enum/shapes.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/enum/text.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/errors.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/exc.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/media.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/package.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/__init__.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/_base.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/chart.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/coreprops.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/embeddedpackage.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/image.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/media.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/presentation.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/parts/slide.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/presentation.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/autoshape.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/base.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/connector.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/freeform.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/graphfrm.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/group.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/picture.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/placeholder.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shapes/shapetree.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/shared.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/slide.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/spec.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/table.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/text/__init__.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/text/fonts.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/text/layout.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/text/text.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/types.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/typing.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/units.py +0 -0
- {athena_python_pptx-0.3.0 → athena_python_pptx-0.4.0}/pptx/util.py +0 -0
|
@@ -2,6 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `athena-python-pptx` are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.3.1
|
|
6
|
+
|
|
7
|
+
**Chart title runs, slide insertion, and shape-delete local state — Insight
|
|
8
|
+
Partners session feedback batch.**
|
|
9
|
+
|
|
10
|
+
Investigated [thread_7b324723-…](https://app.athenaintel.com/dashboard/spaces/?session_id=thread_7b324723-a478-4e99-ac8f-6e7a69766292)
|
|
11
|
+
where an agent built a 15-slide LP pitch deck and tripped over three
|
|
12
|
+
SDK rough edges. Each is addressed below.
|
|
13
|
+
|
|
14
|
+
- **`chart.chart_title.text_frame.paragraphs[0].runs[0].font` now works.**
|
|
15
|
+
The `_ChartTitleTextFrame` previously exposed only `text`; iterating
|
|
16
|
+
`paragraphs` raised `AttributeError`, and the agent fell back to
|
|
17
|
+
unstyled titles. The text frame now carries paragraph and run
|
|
18
|
+
proxies; per-run font writes coalesce into a single
|
|
19
|
+
`SetChartTitleRich` patch on the next flush. The simple
|
|
20
|
+
`text_frame.text = "..."` path still uses the cheaper `SetChartTitle`
|
|
21
|
+
patch — no wire-size regression on the no-formatting case.
|
|
22
|
+
|
|
23
|
+
- **`prs.slides.insert(idx, layout)` added.** Previously, placing a new
|
|
24
|
+
slide between two existing slides required `add_slide()` followed by
|
|
25
|
+
`clone(target_index=...)` to shuffle the list — a workaround that
|
|
26
|
+
cloned 11 shapes onto the new slide and then couldn't fully clear
|
|
27
|
+
them. `insert()` emits a single `AddSlide(index=...)` and refreshes
|
|
28
|
+
the local collection.
|
|
29
|
+
|
|
30
|
+
- **`shape.delete()` updates the local `slide.shapes` view immediately.**
|
|
31
|
+
The buffered delete left `len(slide.shapes)` stale, so the
|
|
32
|
+
"Before: 33, After: 33" symptom appeared even when the delete was
|
|
33
|
+
going through correctly server-side. `delete()` now removes the
|
|
34
|
+
shape from the parent `Shapes` collection in addition to queueing
|
|
35
|
+
the `DeleteShape` command. Layout-inherited shapes
|
|
36
|
+
(`source == "layout"`) no-op rather than queue a guaranteed-to-fail
|
|
37
|
+
delete.
|
|
38
|
+
|
|
39
|
+
- **Toolkit prompt updated** to surface the working chart APIs —
|
|
40
|
+
`series.format.fill.solid()` + `series.format.fill.fore_color.rgb`,
|
|
41
|
+
`chart.legend.position`, doughnut/pie chart enums — and the new
|
|
42
|
+
`slide.clear_shapes()` / `prs.slides.insert()` helpers. The
|
|
43
|
+
Insight Partners agent assumed series styling was unsupported and
|
|
44
|
+
skipped per-series brand colors entirely.
|
|
45
|
+
|
|
5
46
|
## 0.1.76
|
|
6
47
|
|
|
7
48
|
**Table cell paragraph alignment now round-trips to OOXML (baseline-parity Gap A2).**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: athena-python-pptx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Drop-in replacement for python-pptx that connects to PPTX Studio for real-time collaboration
|
|
5
5
|
Project-URL: Homepage, https://github.com/pptx-studio/python-sdk
|
|
6
6
|
Project-URL: Documentation, https://docs.pptx-studio.com/sdk/python
|
|
@@ -830,6 +830,67 @@ The default `fit=None` preserves stock python-pptx behaviour. The only
|
|
|
830
830
|
other accepted value is `"contain"`; passing anything else raises
|
|
831
831
|
`ValueError` to fail loudly rather than silently no-op.
|
|
832
832
|
|
|
833
|
+
## `Shapes.add_athena_anchor()` — Athena-only cross-asset screenshot insert
|
|
834
|
+
|
|
835
|
+
Athena extension with no python-pptx analogue. Renders an Athena
|
|
836
|
+
`Anchor` (a structured reference to a region of another asset — sheet
|
|
837
|
+
cells, sheet ranges, etc.) to a PNG and inserts it as a regular
|
|
838
|
+
`Picture` shape on the current slide. The result is a one-shot raster
|
|
839
|
+
snapshot, **not** a live-linked binding — use `add_linked_table()` /
|
|
840
|
+
`add_linked_ole_object()` for refreshable bindings.
|
|
841
|
+
|
|
842
|
+
```python
|
|
843
|
+
from pptx._references import AssetReference, SheetRangeAnchor
|
|
844
|
+
|
|
845
|
+
slide.shapes.add_athena_anchor(
|
|
846
|
+
AssetReference(id="asset_20880ea3-95fb-4577-9a2e-ad11b7773939"),
|
|
847
|
+
SheetRangeAnchor(sheet_id=1, range="A1:F20"),
|
|
848
|
+
Inches(1), Inches(1),
|
|
849
|
+
width=Inches(8),
|
|
850
|
+
)
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
Signature:
|
|
854
|
+
|
|
855
|
+
```python
|
|
856
|
+
add_athena_anchor(
|
|
857
|
+
source: AssetReference,
|
|
858
|
+
anchor: Anchor,
|
|
859
|
+
left: Length,
|
|
860
|
+
top: Length,
|
|
861
|
+
width: Length | None = None,
|
|
862
|
+
height: Length | None = None,
|
|
863
|
+
*,
|
|
864
|
+
name: str | None = None,
|
|
865
|
+
fit: str | None = None, # "contain" — same semantics as add_picture
|
|
866
|
+
) -> Shape
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
Supported anchor types today:
|
|
870
|
+
|
|
871
|
+
| Anchor type | Behaviour |
|
|
872
|
+
|--------------------|----------------------------------------------------------|
|
|
873
|
+
| `SheetCellAnchor` | Renders the single cell as a 1×1 range PNG. |
|
|
874
|
+
| `SheetRangeAnchor` | Renders the A1 range via xlsx-studio's screenshot.png. |
|
|
875
|
+
| `SheetTableAnchor` | Raises `NotImplementedError` (resolve to A1 + retry). |
|
|
876
|
+
| `SlideAnchor` | Raises `NotImplementedError` (no slide-snapshot route). |
|
|
877
|
+
| anything else | Raises `NotImplementedError`. |
|
|
878
|
+
|
|
879
|
+
Sheet anchors route through `GET {ATHENA_XLSX_BASE_URL}/workbooks/:id/screenshot.png`
|
|
880
|
+
with the sandbox's `ATHENA_XLSX_API_KEY` forwarded as a Bearer token —
|
|
881
|
+
xlsx-studio's ownership middleware checks that the calling workspace
|
|
882
|
+
can read the source workbook. Render scale is fixed at 3 (matches
|
|
883
|
+
xlsx-studio's `range-as-asset` default — slide inserts sit at 6–9″
|
|
884
|
+
widths where scale=2 leaves text soft). When `ATHENA_XLSX_BASE_URL` /
|
|
885
|
+
`ATHENA_XLSX_API_KEY` aren't set (e.g. running outside a Daytona
|
|
886
|
+
presentation_exec sandbox), the call raises `ValueError` rather than
|
|
887
|
+
producing a broken picture.
|
|
888
|
+
|
|
889
|
+
For finer control (custom scale, `include_headers`, off-snapshot
|
|
890
|
+
post-processing), fetch the PNG bytes directly via athena-openpyxl's
|
|
891
|
+
`Worksheet.export_range_sync()` and call `add_picture(bytes, …)`
|
|
892
|
+
yourself.
|
|
893
|
+
|
|
833
894
|
---
|
|
834
895
|
|
|
835
896
|
## `Shapes.add_linked_table()` — Athena studio-linking extension (added in Phase 3)
|
|
@@ -72,7 +72,11 @@ class Client:
|
|
|
72
72
|
base_url: Base URL of the API (e.g., "https://api.pptx-studio.com").
|
|
73
73
|
If not provided, uses ATHENA_PPTX_BASE_URL environment variable.
|
|
74
74
|
api_key: Optional API key for authentication.
|
|
75
|
-
If not provided,
|
|
75
|
+
If not provided, falls back to the ATHENA_PPTX_API_KEY
|
|
76
|
+
environment variable, then to ATHENA_API_KEY (the canonical
|
|
77
|
+
Athena user API key — same value, accepted as a fallback so
|
|
78
|
+
code running in sandboxes that only inject ATHENA_API_KEY
|
|
79
|
+
still authenticates).
|
|
76
80
|
timeout: Request timeout in seconds
|
|
77
81
|
|
|
78
82
|
Raises:
|
|
@@ -83,11 +87,13 @@ class Client:
|
|
|
83
87
|
base_url = os.environ.get("ATHENA_PPTX_BASE_URL")
|
|
84
88
|
if base_url is None:
|
|
85
89
|
raise ValueError(
|
|
86
|
-
"base_url must be provided or ATHENA_PPTX_BASE_URL
|
|
90
|
+
"base_url must be provided or the ATHENA_PPTX_BASE_URL "
|
|
91
|
+
"environment variable must be set. Example: "
|
|
92
|
+
'ATHENA_PPTX_BASE_URL="https://pptx-studio.prd.athenaintel.com".'
|
|
87
93
|
)
|
|
88
94
|
|
|
89
95
|
if api_key is None:
|
|
90
|
-
api_key = os.environ.get("ATHENA_PPTX_API_KEY")
|
|
96
|
+
api_key = os.environ.get("ATHENA_PPTX_API_KEY") or os.environ.get("ATHENA_API_KEY")
|
|
91
97
|
|
|
92
98
|
self.base_url = base_url.rstrip("/")
|
|
93
99
|
self.api_key = api_key
|
|
@@ -129,7 +135,18 @@ class Client:
|
|
|
129
135
|
def _handle_response(self, response: requests.Response) -> Any:
|
|
130
136
|
"""Handle API response, raising appropriate errors."""
|
|
131
137
|
if response.status_code == 401:
|
|
132
|
-
|
|
138
|
+
if not self.api_key:
|
|
139
|
+
raise AuthenticationError(
|
|
140
|
+
"No API key was sent. Pass api_key= to Presentation(...) "
|
|
141
|
+
"or set ATHENA_PPTX_API_KEY (or ATHENA_API_KEY as a "
|
|
142
|
+
"fallback) in the environment."
|
|
143
|
+
)
|
|
144
|
+
raise AuthenticationError(
|
|
145
|
+
"Invalid or expired API key. The pptx-studio API rejected the "
|
|
146
|
+
"credentials. Verify ATHENA_PPTX_API_KEY (or the ATHENA_API_KEY "
|
|
147
|
+
"fallback) is set to a valid Athena user API key for the "
|
|
148
|
+
"current workspace."
|
|
149
|
+
)
|
|
133
150
|
|
|
134
151
|
if response.status_code == 409:
|
|
135
152
|
data = response.json() if response.text else {}
|
|
@@ -416,7 +433,7 @@ class Client:
|
|
|
416
433
|
if name is None:
|
|
417
434
|
name = os.path.basename(file_path)
|
|
418
435
|
# Remove extension
|
|
419
|
-
if name.endswith(
|
|
436
|
+
if name.endswith(".pptx") or name.endswith(".potx"):
|
|
420
437
|
name = name[:-5]
|
|
421
438
|
|
|
422
439
|
# Step 1: Create deck to get presigned URL
|
|
@@ -496,7 +513,7 @@ class Client:
|
|
|
496
513
|
# Use filename as name if not provided
|
|
497
514
|
if name is None:
|
|
498
515
|
name = os.path.basename(file_path)
|
|
499
|
-
if name.endswith(
|
|
516
|
+
if name.endswith(".pptx") or name.endswith(".potx"):
|
|
500
517
|
name = name[:-5]
|
|
501
518
|
|
|
502
519
|
# Step 1: Create deck to get presigned URL
|
|
@@ -800,9 +817,7 @@ class Client:
|
|
|
800
817
|
return self._download(download_url)
|
|
801
818
|
|
|
802
819
|
if status["status"] in ("failed", "error"):
|
|
803
|
-
raise ExportError(
|
|
804
|
-
status.get("error", "Export failed"), job_id
|
|
805
|
-
)
|
|
820
|
+
raise ExportError(status.get("error", "Export failed"), job_id)
|
|
806
821
|
|
|
807
822
|
time.sleep(poll_interval)
|
|
808
823
|
|
|
@@ -870,9 +885,7 @@ class Client:
|
|
|
870
885
|
return self._download(image_url)
|
|
871
886
|
|
|
872
887
|
if status["status"] in ("failed", "error"):
|
|
873
|
-
raise RenderError(
|
|
874
|
-
status.get("error", "Render failed"), job_id
|
|
875
|
-
)
|
|
888
|
+
raise RenderError(status.get("error", "Render failed"), job_id)
|
|
876
889
|
|
|
877
890
|
time.sleep(poll_interval)
|
|
878
891
|
|
|
@@ -1464,6 +1464,23 @@ class SetGradientFill(Command):
|
|
|
1464
1464
|
"stops"
|
|
1465
1465
|
)
|
|
1466
1466
|
|
|
1467
|
+
def to_dict(self) -> dict[str, Any]:
|
|
1468
|
+
"""Serialize, camelCasing each stop's ``color_hex`` to ``colorHex`` for the server schema."""
|
|
1469
|
+
result = super().to_dict()
|
|
1470
|
+
if self.stops is not None:
|
|
1471
|
+
camel_stops: list[dict[str, Any]] = []
|
|
1472
|
+
for stop in self.stops:
|
|
1473
|
+
camel: dict[str, Any] = {
|
|
1474
|
+
"position": stop.get("position"),
|
|
1475
|
+
"colorHex": stop.get("color_hex"),
|
|
1476
|
+
}
|
|
1477
|
+
transparency = stop.get("transparency")
|
|
1478
|
+
if transparency is not None:
|
|
1479
|
+
camel["transparency"] = transparency
|
|
1480
|
+
camel_stops.append(camel)
|
|
1481
|
+
result["stops"] = camel_stops
|
|
1482
|
+
return result
|
|
1483
|
+
|
|
1467
1484
|
|
|
1468
1485
|
@dataclass
|
|
1469
1486
|
class SetShapeZOrder(Command):
|