Skip to content

Commit c5c242b

Browse files
committed
make render_mjml private
1 parent a51d54c commit c5c242b

File tree

6 files changed

+48
-41
lines changed

6 files changed

+48
-41
lines changed

emailer_lib/ingress.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .structs import IntermediateEmail
99
from .mjml import MJMLTag
1010
from .mjml.image_processor import _process_mjml_images
11+
import warnings
1112

1213
__all__ = [
1314
"redmail_to_intermediate_email",
@@ -63,9 +64,10 @@ def mjml_to_intermediate_email(
6364
# Handle MJMLTag objects by preprocessing images
6465
if isinstance(mjml_content, MJMLTag):
6566
processed_mjml, inline_attachments = _process_mjml_images(mjml_content)
66-
mjml_markup = processed_mjml.render_mjml()
67+
mjml_markup = processed_mjml._render_mjml()
6768
else:
6869
# String-based MJML, no preprocessing needed
70+
warnings.warn("MJMLTag not detected; treating input as plaintext MJML markup", UserWarning)
6971
mjml_markup = mjml_content
7072
inline_attachments = {}
7173

emailer_lib/mjml/_core.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,12 @@ def __init__(
126126
# if self.content is not None:
127127
# self.children = []
128128

129-
def render_mjml(self, indent: int = 0, eol: str = "\n") -> str:
129+
def _render_mjml(self, indent: int = 0, eol: str = "\n") -> str:
130130
"""
131131
Render MJMLTag and its children to MJML markup.
132132
Ported from htmltools Tag rendering logic.
133133
134-
Note: BytesIO/bytes in image src attributes are not supported by render_mjml().
134+
Note: BytesIO/bytes in image src attributes are not supported by _render_mjml().
135135
Pass the MJMLTag directly to mjml_to_intermediate_email() instead.
136136
"""
137137

@@ -150,7 +150,7 @@ def _flatten(children):
150150
if isinstance(src_value, (bytes, BytesIO)):
151151
raise ValueError(
152152
"Cannot render MJML with BytesIO/bytes in image src attribute. "
153-
"Pass the MJMLTag object directly to mjml_to_intermediate_email() instead of calling render_mjml() first. "
153+
"Pass the MJMLTag object directly to mjml_to_intermediate_email() instead of calling _render_mjml() first. "
154154
"Example: i_email = mjml_to_intermediate_email(doc)"
155155
)
156156

@@ -167,7 +167,7 @@ def _flatten(children):
167167
child_strs = []
168168
for child in _flatten(self.children):
169169
if isinstance(child, MJMLTag):
170-
child_strs.append(child.render_mjml(indent + 2, eol))
170+
child_strs.append(child._render_mjml(indent + 2, eol))
171171
else:
172172
child_strs.append(str(child))
173173
if child_strs:
@@ -181,12 +181,20 @@ def _flatten(children):
181181
return f"{pad}<{self.tagName}{attr_str}></{self.tagName}>"
182182

183183
def _repr_html_(self):
184-
return self.to_html()
184+
from ..ingress import mjml_to_intermediate_email
185+
return mjml_to_intermediate_email(self)._repr_html_()
185186

187+
# TODO: make something deliberate
186188
def __repr__(self) -> str:
187-
return self.render_mjml()
188-
189-
def to_html(self, **mjml2html_kwargs):
189+
warnings.warn(
190+
f"__repr__ not yet fully implemented for MJMLTag({self.tagName})",
191+
UserWarning,
192+
stacklevel=2,
193+
)
194+
return f"<MJMLTag({self.tagName})>"
195+
196+
# warning explain that they are not to pass this to intermediate email
197+
def to_html(self, **mjml2html_kwargs) -> str:
190198
"""
191199
Render MJMLTag to HTML using mjml2html.
192200
@@ -201,11 +209,11 @@ def to_html(self, **mjml2html_kwargs):
201209
Returns
202210
-------
203211
str
204-
Result from mjml2html containing html content
212+
Result from `mjml-python.mjml2html()` containing html content
205213
"""
206214
if self.tagName == "mjml":
207215
# Already a complete MJML document
208-
mjml_markup = self.render_mjml()
216+
mjml_markup = self._render_mjml()
209217
elif self.tagName == "mj-body":
210218
# Wrap only in mjml tag
211219
warnings.warn(
@@ -216,7 +224,7 @@ def to_html(self, **mjml2html_kwargs):
216224
stacklevel=2,
217225
)
218226
wrapped = MJMLTag("mjml", self)
219-
mjml_markup = wrapped.render_mjml()
227+
mjml_markup = wrapped._render_mjml()
220228
else:
221229
# Warn and wrap in mjml/mj-body
222230
warnings.warn(
@@ -228,6 +236,6 @@ def to_html(self, **mjml2html_kwargs):
228236
)
229237
# Wrap in mjml and mj-body
230238
wrapped = MJMLTag("mjml", MJMLTag("mj-body", self))
231-
mjml_markup = wrapped.render_mjml()
239+
mjml_markup = wrapped._render_mjml()
232240

233241
return mjml2html(mjml_markup, **mjml2html_kwargs)

emailer_lib/mjml/image_processor.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ def _process_mjml_images(mjml_tag: MJMLTag) -> Tuple[MJMLTag, Dict[str, str]]:
5858
with BytesIO or bytes in their src attribute. It converts these to CID references
5959
and extracts the base64 data for the inline_attachments dictionary.
6060
61-
Note: This function should be called before render_mjml(). If render_mjml() is called
62-
on a tag with BytesIO/bytes, it will raise an error directing you to use this approach.
63-
6461
Parameters
6562
----------
6663
mjml_tag

emailer_lib/mjml/tests/test_core.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,41 +37,41 @@ def test_tag_with_dict_attributes():
3737

3838
def test_tag_filters_none_children():
3939
tag = MJMLTag("mj-column", MJMLTag("mj-text", content="Text"), None)
40-
mjml_content = tag.render_mjml()
40+
mjml_content = tag._render_mjml()
4141

4242
# None should not appear in output
4343
assert mjml_content.count("<mj-text>") == 1
4444

4545

4646
def test_render_empty_tag():
4747
tag = MJMLTag("mj-spacer")
48-
mjml_content = tag.render_mjml()
48+
mjml_content = tag._render_mjml()
4949
assert mjml_content == "<mj-spacer></mj-spacer>"
5050

5151

5252
def test_render_with_attributes():
5353
tag = MJMLTag("mj-spacer", attributes={"height": "20px"})
54-
mjml_content = tag.render_mjml()
54+
mjml_content = tag._render_mjml()
5555
assert mjml_content == '<mj-spacer height="20px"></mj-spacer>'
5656

5757

5858
def test_render_with_custom_indent():
5959
tag = MJMLTag("mj-text", content="Hello")
60-
mjml_content = tag.render_mjml(indent=4)
60+
mjml_content = tag._render_mjml(indent=4)
6161
assert mjml_content.startswith(" <mj-text>")
6262

6363

6464
def test_render_with_custom_eol():
6565
tag = MJMLTag("mj-text", content="Hello")
66-
mjml_content = tag.render_mjml(eol="\r\n")
66+
mjml_content = tag._render_mjml(eol="\r\n")
6767
assert "\r\n" in mjml_content
6868

6969

7070
def test_render_nested_tags():
7171
tag = MJMLTag(
7272
"mj-section", MJMLTag("mj-column", MJMLTag("mj-text", content="Nested"))
7373
)
74-
mjml_content = tag.render_mjml()
74+
mjml_content = tag._render_mjml()
7575

7676
assert "<mj-section>" in mjml_content
7777
assert "<mj-column>" in mjml_content
@@ -82,7 +82,7 @@ def test_render_nested_tags():
8282
def test_render_with_string_and_tag_children():
8383
child_tag = MJMLTag("mj-text", content="Tagged")
8484
tag = MJMLTag("mj-column", "Plain text", child_tag, "More text")
85-
mjml_content = tag.render_mjml()
85+
mjml_content = tag._render_mjml()
8686

8787
assert "Plain text" in mjml_content
8888
assert "<mj-text>" in mjml_content
@@ -92,7 +92,7 @@ def test_render_with_string_and_tag_children():
9292
def test_repr_returns_mjml():
9393
tag = MJMLTag("mj-text", content="Hello")
9494

95-
assert repr(tag) == tag.render_mjml()
95+
assert repr(tag) == tag._render_mjml()
9696

9797

9898
def test_to_html_with_complete_mjml_document():
@@ -166,7 +166,7 @@ def test_children_sequence_flattening():
166166
assert tag.children[1] == child2
167167
assert tag.children[2] == child3
168168

169-
mjml_content = tag.render_mjml()
169+
mjml_content = tag._render_mjml()
170170

171171
assert mjml_content.count("<mj-text>") == 3
172172
assert "Text 1" in mjml_content
@@ -182,7 +182,7 @@ def test_render_mjml_raises_on_bytesio_in_image_src():
182182
)
183183

184184
with pytest.raises(ValueError, match="Cannot render MJML with BytesIO/bytes"):
185-
image_tag.render_mjml()
185+
image_tag._render_mjml()
186186

187187

188188
def test_render_mjml_raises_on_bytes_in_image_src():
@@ -193,7 +193,7 @@ def test_render_mjml_raises_on_bytes_in_image_src():
193193
)
194194

195195
with pytest.raises(ValueError, match="Cannot render MJML with BytesIO/bytes"):
196-
image_tag.render_mjml()
196+
image_tag._render_mjml()
197197

198198

199199
def test_tagattr_dict_stores_bytesio():

emailer_lib/mjml/tests/test_tags.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_container_tag_accepts_children():
3939
assert len(sec.children) == 1
4040
assert sec.children[0].tagName == "mj-column"
4141

42-
mjml_content = sec.render_mjml()
42+
mjml_content = sec._render_mjml()
4343
assert "<mj-section>" in mjml_content
4444
assert "<mj-column>" in mjml_content
4545
assert "<mj-text>" in mjml_content
@@ -53,7 +53,7 @@ def test_container_tag_accepts_attributes():
5353
assert sec.attrs["background-color"] == "#fff"
5454
assert sec.attrs["padding"] == "20px"
5555

56-
mjml_content = sec.render_mjml()
56+
mjml_content = sec._render_mjml()
5757
assert '<mj-section background-color="#fff" padding="20px">' in mjml_content
5858

5959

@@ -66,7 +66,7 @@ def test_container_tag_accepts_children_and_attrs():
6666
assert len(sec.children) == 2
6767
assert sec.attrs["background-color"] == "#f0f0f0"
6868

69-
mjml_content = sec.render_mjml()
69+
mjml_content = sec._render_mjml()
7070
assert 'background-color="#f0f0f0"' in mjml_content
7171
assert "Col 1" in mjml_content
7272
assert "Col 2" in mjml_content
@@ -79,7 +79,7 @@ def test_leaf_tag_accepts_content():
7979
assert txt.tagName == "mj-text"
8080
assert txt.content == "Hello World"
8181

82-
mjml_content = txt.render_mjml()
82+
mjml_content = txt._render_mjml()
8383
assert mjml_content == "<mj-text>\nHello World\n</mj-text>"
8484

8585

@@ -89,7 +89,7 @@ def test_leaf_tag_accepts_attributes():
8989
assert txt.attrs["color"] == "red"
9090
assert txt.attrs["font-size"] == "16px"
9191

92-
mjml_content = txt.render_mjml()
92+
mjml_content = txt._render_mjml()
9393
assert 'color="red"' in mjml_content
9494
assert 'font-size="16px"' in mjml_content
9595
assert "Hello" in mjml_content
@@ -108,7 +108,7 @@ def test_button_is_leaf_tag():
108108
assert btn.content == "Click Me"
109109
assert btn.attrs["href"] == "https://example.com"
110110

111-
mjml_content = btn.render_mjml()
111+
mjml_content = btn._render_mjml()
112112
assert 'href="https://example.com"' in mjml_content
113113
assert "Click Me" in mjml_content
114114
assert "<mj-button" in mjml_content
@@ -158,7 +158,7 @@ def test_raw_tag():
158158
assert r.tagName == "mj-raw"
159159
assert r.content == "<div>Custom HTML</div>"
160160

161-
mjml_content = r.render_mjml()
161+
mjml_content = r._render_mjml()
162162
assert mjml_content == "<mj-raw>\n<div>Custom HTML</div>\n</mj-raw>"
163163

164164

@@ -167,7 +167,7 @@ def test_table_tag():
167167
assert tbl.tagName == "mj-table"
168168
assert "<table>" in tbl.content
169169

170-
mjml_content = tbl.render_mjml()
170+
mjml_content = tbl._render_mjml()
171171
assert "<mj-table>" in mjml_content
172172
assert "<table><tr><td>Cell</td></tr></table>" in mjml_content
173173

@@ -195,7 +195,7 @@ def test_image_tag():
195195
assert img.attrs["src"] == "https://example.com/image.jpg"
196196
assert img.attrs["alt"] == "Test Image"
197197

198-
mjml_content = img.render_mjml()
198+
mjml_content = img._render_mjml()
199199
assert 'src="https://example.com/image.jpg"' in mjml_content
200200
assert 'alt="Test Image"' in mjml_content
201201
assert "<mj-image" in mjml_content
@@ -214,7 +214,7 @@ def test_attributes_container_with_mj_all_and_classes():
214214
assert attrs.children[1].tagName == "mj-class"
215215
assert attrs.children[2].tagName == "mj-class"
216216

217-
mjml_content = attrs.render_mjml()
217+
mjml_content = attrs._render_mjml()
218218
assert "<mj-attributes>" in mjml_content
219219
assert "<mj-all" in mjml_content
220220
assert 'font-family="Arial"' in mjml_content
@@ -226,7 +226,7 @@ def test_component_with_mj_class_attribute():
226226
txt = text(attributes={"mj-class": "blue big"}, content="Hello World!")
227227
assert txt.attrs["mj-class"] == "blue big"
228228

229-
mjml_content = txt.render_mjml()
229+
mjml_content = txt._render_mjml()
230230
assert 'mj-class="blue big"' in mjml_content
231231
assert "Hello World!" in mjml_content
232232

@@ -258,7 +258,7 @@ def test_full_document_with_attributes():
258258
assert attrs_tag.tagName == "mj-attributes"
259259
assert len(attrs_tag.children) == 4
260260

261-
mjml_content = doc.render_mjml()
261+
mjml_content = doc._render_mjml()
262262
assert "<mj-attributes>" in mjml_content
263263
assert '<mj-text padding="0"' in mjml_content
264264
assert 'name="blue"' in mjml_content

emailer_lib/tests/test_ingress.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ def test_mjml_render_mjml_with_bytesio_raises_error():
207207
)
208208
)
209209

210-
# Calling render_mjml() should raise an error with a helpful message
210+
# Calling _render_mjml() should raise an error with a helpful message
211211
with pytest.raises(ValueError, match="Cannot render MJML with BytesIO/bytes"):
212-
mjml_tag.render_mjml()
212+
mjml_tag._render_mjml()
213213

214214
# But passing the tag directly to mjml_to_intermediate_email should work
215215
result = mjml_to_intermediate_email(mjml_tag)

0 commit comments

Comments
 (0)