athena-python-pptx 0.4.2__tar.gz → 0.4.3__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 (86) hide show
  1. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/PKG-INFO +1 -1
  2. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/__init__.py +1 -1
  3. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/dml/color.py +44 -0
  4. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/__init__.py +32 -2
  5. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pyproject.toml +1 -1
  6. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/uv.lock +2 -2
  7. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/.gitignore +0 -0
  8. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/API_PARITY_REPORT.md +0 -0
  9. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/CHANGELOG.md +0 -0
  10. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/CLAUDE.md +0 -0
  11. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/DEV-GUIDE.md +0 -0
  12. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/PARITY_QUESTIONS.md +0 -0
  13. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/PUBLISHING.md +0 -0
  14. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/README.md +0 -0
  15. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/docs/API_PARITY_EXCEPTIONS.md +0 -0
  16. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/docs/athena-api.json +0 -0
  17. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/docs/athena-api.md +0 -0
  18. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/_athena_extension.py +0 -0
  19. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/_ptc.py +0 -0
  20. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/_references.py +0 -0
  21. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/action.py +0 -0
  22. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/batching.py +0 -0
  23. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/__init__.py +0 -0
  24. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/axis.py +0 -0
  25. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/category.py +0 -0
  26. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/chart.py +0 -0
  27. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/data.py +0 -0
  28. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/datalabel.py +0 -0
  29. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/legend.py +0 -0
  30. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/marker.py +0 -0
  31. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/plot.py +0 -0
  32. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/point.py +0 -0
  33. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/series.py +0 -0
  34. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/chart/xlsx.py +0 -0
  35. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/client.py +0 -0
  36. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/commands.py +0 -0
  37. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/decorators.py +0 -0
  38. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/dml/__init__.py +0 -0
  39. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/dml/chtfmt.py +0 -0
  40. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/dml/effect.py +0 -0
  41. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/dml/fill.py +0 -0
  42. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/dml/line.py +0 -0
  43. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/docgen.py +0 -0
  44. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/enum/__init__.py +0 -0
  45. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/enum/action.py +0 -0
  46. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/enum/chart.py +0 -0
  47. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/enum/dml.py +0 -0
  48. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/enum/lang.py +0 -0
  49. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/enum/shapes.py +0 -0
  50. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/enum/text.py +0 -0
  51. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/errors.py +0 -0
  52. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/exc.py +0 -0
  53. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/media.py +0 -0
  54. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/package.py +0 -0
  55. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/__init__.py +0 -0
  56. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/_base.py +0 -0
  57. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/chart.py +0 -0
  58. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/coreprops.py +0 -0
  59. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/embeddedpackage.py +0 -0
  60. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/image.py +0 -0
  61. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/media.py +0 -0
  62. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/presentation.py +0 -0
  63. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/parts/slide.py +0 -0
  64. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/presentation.py +0 -0
  65. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/autoshape.py +0 -0
  66. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/base.py +0 -0
  67. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/connector.py +0 -0
  68. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/freeform.py +0 -0
  69. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/graphfrm.py +0 -0
  70. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/group.py +0 -0
  71. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/picture.py +0 -0
  72. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/placeholder.py +0 -0
  73. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shapes/shapetree.py +0 -0
  74. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/shared.py +0 -0
  75. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/slide.py +0 -0
  76. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/slides.py +0 -0
  77. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/spec.py +0 -0
  78. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/table.py +0 -0
  79. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/text/__init__.py +0 -0
  80. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/text/fonts.py +0 -0
  81. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/text/layout.py +0 -0
  82. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/text/text.py +0 -0
  83. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/types.py +0 -0
  84. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/typing.py +0 -0
  85. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/units.py +0 -0
  86. {athena_python_pptx-0.4.2 → athena_python_pptx-0.4.3}/pptx/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: athena-python-pptx
3
- Version: 0.4.2
3
+ Version: 0.4.3
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
@@ -133,7 +133,7 @@ def flush_all() -> None:
133
133
  _active_buffers[:] = alive
134
134
 
135
135
 
136
- __version__ = "0.4.2"
136
+ __version__ = "0.4.3"
137
137
 
138
138
  __all__ = [
139
139
  # Main entry point
@@ -50,6 +50,50 @@ def theme_color_to_scheme_name(theme_color: "MSO_THEME_COLOR") -> Optional[str]:
50
50
  return _THEME_COLOR_TO_SCHEME_NAME.get(value)
51
51
 
52
52
 
53
+ # Reverse of ``_THEME_COLOR_TO_SCHEME_NAME`` for the read path: map an OOXML
54
+ # ``<a:schemeClr val="...">`` name back to its canonical ``MSO_THEME_COLOR``.
55
+ # The forward map is many-to-one (both DARK_1 and TEXT_1 spell 'tx1'); on the
56
+ # way back python-pptx surfaces the index-13..16 spellings for the bg*/tx*
57
+ # names (TEXT_1/BACKGROUND_1/TEXT_2/BACKGROUND_2) and the dk*/lt* aliases for
58
+ # DARK_1/LIGHT_1/DARK_2/LIGHT_2, which is what we reproduce here.
59
+ _SCHEME_NAME_TO_THEME_COLOR = {
60
+ "tx1": 13, # TEXT_1
61
+ "bg1": 14, # BACKGROUND_1
62
+ "tx2": 16, # TEXT_2
63
+ "bg2": 15, # BACKGROUND_2
64
+ "dk1": 1, # DARK_1
65
+ "lt1": 2, # LIGHT_1
66
+ "dk2": 3, # DARK_2
67
+ "lt2": 4, # LIGHT_2
68
+ "accent1": 5,
69
+ "accent2": 6,
70
+ "accent3": 7,
71
+ "accent4": 8,
72
+ "accent5": 9,
73
+ "accent6": 10,
74
+ "hlink": 11, # HYPERLINK
75
+ "folHlink": 12, # FOLLOWED_HYPERLINK
76
+ }
77
+
78
+
79
+ def scheme_name_to_theme_color(scheme_name: Optional[str]) -> Optional["MSO_THEME_COLOR"]:
80
+ """Convert an OOXML ``<a:schemeClr>`` name back to an ``MSO_THEME_COLOR``.
81
+
82
+ Inverse of :func:`theme_color_to_scheme_name`, used by the read path so a
83
+ re-opened deck exposes ``fill.fore_color.theme_color`` /
84
+ ``line.color.theme_color`` instead of ``None``. Returns ``None`` for
85
+ unknown names (e.g. ``phClr``) so callers fall back to sRGB.
86
+ """
87
+ if not scheme_name:
88
+ return None
89
+ value = _SCHEME_NAME_TO_THEME_COLOR.get(scheme_name)
90
+ if value is None:
91
+ return None
92
+ from ..enum.dml import MSO_THEME_COLOR
93
+
94
+ return MSO_THEME_COLOR(value)
95
+
96
+
53
97
  class RGBColor:
54
98
  """
55
99
  Immutable RGB color value, matching the standard python-pptx API.
@@ -635,11 +635,27 @@ class FillFormat:
635
635
  def __init__(self, shape: Shape):
636
636
  self._shape = shape
637
637
  self._solid_color: Optional[str] = shape._properties.get("fillColorHex")
638
+ # Scheme (theme) fill read back from the snapshot. Initializing it here
639
+ # (rather than only in ``_on_color_change``) both fixes a latent
640
+ # AttributeError when ``_scheme_color`` is read before any write and
641
+ # lets a re-opened theme-colored fill round-trip on re-export.
642
+ self._scheme_color: Optional[str] = shape._properties.get("fillSchemeColor")
638
643
  self._transparency: float = 0.0
639
- self._type: Optional[str] = 'solid' if self._solid_color else None
644
+ # A scheme fill with no explicit sRGB is still a solid fill.
645
+ self._type: Optional[str] = 'solid' if (self._solid_color or self._scheme_color) else None
640
646
  # Initialize fore_color ColorFormat
641
647
  rgb = RGBColor.from_string(self._solid_color) if self._solid_color else None
642
648
  self._fore_color_format = _FillColorFormat(self, rgb=rgb)
649
+ # Surface ``fore_color.theme_color`` for a scheme fill (no sRGB hex) so
650
+ # the agent "restyle a deck I just opened" workflow reads back the theme
651
+ # color instead of None. Set the attribute directly to avoid triggering
652
+ # the setter's write-emit on a pure read.
653
+ if self._scheme_color and not self._solid_color:
654
+ from ..dml.color import scheme_name_to_theme_color
655
+
656
+ theme = scheme_name_to_theme_color(self._scheme_color)
657
+ if theme is not None:
658
+ self._fore_color_format._theme_color = theme
643
659
 
644
660
  def solid(self) -> None:
645
661
  """
@@ -940,11 +956,25 @@ class LineFormat:
940
956
  def __init__(self, shape: Shape):
941
957
  self._shape = shape
942
958
  self._color_hex: Optional[str] = shape._properties.get("strokeColorHex")
959
+ # Scheme (theme) line color; initialized here so it round-trips and so
960
+ # the setters that reference ``_scheme_color`` never hit an
961
+ # AttributeError on a fresh read.
962
+ self._scheme_color: Optional[str] = shape._properties.get("strokeSchemeColor")
943
963
  self._width_emu: int = shape._properties.get("strokeWidthEmu", 12700) # Default 1pt
944
- self._dash_style: str = 'solid'
964
+ # Read the persisted dash style back (defaults to solid) so a re-opened
965
+ # deck exposes ``line.dash_style`` instead of always 'solid'. The Y.Doc
966
+ # and SDK share the same dash vocabulary, so no mapping is needed.
967
+ self._dash_style: str = shape._properties.get("strokeDashStyle") or 'solid'
945
968
  # Initialize color ColorFormat
946
969
  rgb = RGBColor.from_string(self._color_hex) if self._color_hex else None
947
970
  self._color_format = _LineColorFormat(self, rgb=rgb)
971
+ # Surface ``color.theme_color`` for a scheme line color (no sRGB hex).
972
+ if self._scheme_color and not self._color_hex:
973
+ from ..dml.color import scheme_name_to_theme_color
974
+
975
+ theme = scheme_name_to_theme_color(self._scheme_color)
976
+ if theme is not None:
977
+ self._color_format._theme_color = theme
948
978
 
949
979
  @property
950
980
  def color(self) -> _LineColorFormat:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "athena-python-pptx"
7
- version = "0.4.2"
7
+ version = "0.4.3"
8
8
  description = "Drop-in replacement for python-pptx that connects to PPTX Studio for real-time collaboration"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -49,7 +49,7 @@ wheels = [
49
49
 
50
50
  [[package]]
51
51
  name = "athena-python-pptx"
52
- version = "0.4.2"
52
+ version = "0.4.3"
53
53
  source = { editable = "." }
54
54
  dependencies = [
55
55
  { name = "requests" },
@@ -338,7 +338,7 @@ name = "exceptiongroup"
338
338
  version = "1.3.1"
339
339
  source = { registry = "https://pypi.org/simple" }
340
340
  dependencies = [
341
- { name = "typing-extensions", marker = "python_full_version < '3.13'" },
341
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
342
342
  ]
343
343
  sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
344
344
  wheels = [