Skip to content

Commit 7e2efa1

Browse files
rgaudinbenoit74
authored andcommitted
updated tests for metadata/illus/typing updates
1 parent e669d24 commit 7e2efa1

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

tests/zim/test_metadata.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,102 @@ def test_std_metadata_values():
508508

509509
def test_raw_metadata():
510510
assert metadata.Metadata(name="Name", value=b"hello")
511+
512+
513+
def test_decorators():
514+
@metadata.allow_empty
515+
class MyMetadata(metadata.XCustomTextMetadata): ...
516+
517+
assert MyMetadata("Test", "value").libzim_value == b"value"
518+
519+
@metadata.allow_duplicates
520+
class MyMetadata2(metadata.TextListBasedMetadata):
521+
join_list_with = "|"
522+
523+
assert (
524+
MyMetadata2(name="Test", value=["value", "hello", "value"]).libzim_value
525+
== b"value|hello|value"
526+
)
527+
528+
raw_value = "\t\n\r\n \tA val \t\awith \bcontrol chars\v\n"
529+
530+
class MyMetadata3(metadata.TextBasedMetadata):
531+
require_text_cleanup = False
532+
533+
assert MyMetadata3(name="Test", value=raw_value).libzim_value == raw_value.encode(
534+
"UTF-8"
535+
)
536+
537+
@metadata.allow_duplicates
538+
class MyMetadata4(metadata.TextListBasedMetadata):
539+
require_textlist_cleanup = False
540+
join_list_with = "|"
541+
542+
assert MyMetadata4(
543+
name="Test", value=(raw_value, raw_value)
544+
).libzim_value == "|".join([raw_value, raw_value]).encode("UTF-8")
545+
546+
547+
def test_custom_ones():
548+
textval = "value"
549+
value = textval.encode("UTF-8")
550+
assert metadata.CustomMetadata("Test", value).libzim_value == value
551+
assert metadata.XCustomMetadata("Name", value).libzim_value == value
552+
assert metadata.XCustomMetadata("Name", value).name == "X-Name"
553+
assert metadata.CustomTextMetadata("Test", textval).libzim_value == value
554+
assert metadata.XCustomTextMetadata("Name", textval).libzim_value == value
555+
assert metadata.XCustomTextMetadata("Name", textval).name == "X-Name"
556+
with pytest.raises(ValueError, match="must be X- prefixed"):
557+
metadata.CustomMetadata("Name", value)
558+
with pytest.raises(ValueError, match="must be X- prefixed"):
559+
metadata.CustomTextMetadata("Name", textval)
560+
561+
562+
def test_mandatory_zim_metadata_keys():
563+
# as per the spec on 2024-12-13
564+
assert len(metadata.MANDATORY_ZIM_METADATA_KEYS) >= 8
565+
assert "Illustration_48x48@1" in metadata.MANDATORY_ZIM_METADATA_KEYS
566+
567+
568+
def test_default_dev_zim_metadata():
569+
assert isinstance(metadata.DEFAULT_DEV_ZIM_METADATA, metadata.StandardMetadataList)
570+
# as per the spec on 2024-12-13
571+
assert len(metadata.DEFAULT_DEV_ZIM_METADATA.values()) == 8
572+
573+
574+
def test_get_binary_from(png_image):
575+
with open(png_image, "rb") as fh:
576+
png_data = fh.read()
577+
# bytes input
578+
assert metadata.Metadata(value=png_data, name="Test").libzim_value == png_data
579+
# io.BytesIO input
580+
assert (
581+
metadata.Metadata(value=io.BytesIO(png_data), name="Test").libzim_value
582+
== png_data
583+
)
584+
# BaseIO input
585+
with open(png_image, "rb") as fh:
586+
assert metadata.Metadata(value=fh, name="Test").libzim_value == png_data
587+
588+
# unseekbale BaseIO
589+
def notseekable():
590+
return False
591+
592+
with open(png_image, "rb") as fh:
593+
fh.seekable = notseekable
594+
assert metadata.Metadata(value=fh, name="Test").libzim_value == png_data
595+
596+
597+
def test_ensure_missingname_raises():
598+
with pytest.raises(OSError, match="name missing"):
599+
metadata.Metadata(b"yello")
600+
601+
602+
def test_mimetype_usage():
603+
mimetype = "video/webm"
604+
assert metadata.Metadata(b"hello", "Test", mimetype=mimetype).mimetype == mimetype
605+
assert metadata.Metadata(b"hello", "Test").mimetype == "text/plain;charset=UTF-8"
606+
assert (
607+
metadata.DEFAULT_DEV_ZIM_METADATA.Illustration_48x48_at_1.mimetype
608+
== "image/png"
609+
)

tests/zim/test_typing.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from zimscraperlib.typing import Callback
2+
3+
4+
class GlobalCounter:
5+
count: int = 0
6+
7+
8+
def update_counter() -> int:
9+
GlobalCounter.count += 1
10+
return GlobalCounter.count
11+
12+
13+
def update_counter_args(bump: int) -> int:
14+
GlobalCounter.count += bump
15+
return GlobalCounter.count
16+
17+
18+
def update_counter_kwargs(*, bump: int) -> int:
19+
GlobalCounter.count += bump
20+
return GlobalCounter.count
21+
22+
23+
def update_counter_args_and_kwargs(bump: int, *, factor: int) -> int:
24+
GlobalCounter.count += bump * factor
25+
return GlobalCounter.count
26+
27+
28+
def test_callback_init():
29+
assert Callback(update_counter)
30+
assert Callback(update_counter).callable
31+
GlobalCounter.count = 0
32+
assert GlobalCounter.count == 0
33+
Callback(update_counter_args, args=(1,)).call()
34+
assert GlobalCounter.count == 1
35+
Callback(update_counter_args, kwargs={"bump": 1}).call()
36+
assert GlobalCounter.count == 2
37+
Callback(update_counter_kwargs, kwargs={"bump": 1}).call()
38+
assert GlobalCounter.count == 3
39+
Callback(update_counter_args_and_kwargs, args=(1,), kwargs={"factor": 2}).call()
40+
assert GlobalCounter.count == 5

tests/zim/test_zim_creator.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ def test_add_item_for(tmp_path):
181181
creator.add_item_for(path="welcome", title="hello")
182182

183183

184+
def test_additem_bad_content(tmp_path):
185+
with Creator(tmp_path / "test.zim", "welcome").config_dev_metadata() as creator:
186+
with pytest.raises(RuntimeError, match="Unexpected type for content"):
187+
si = StaticItem(path="welcome", content="hello")
188+
si.content = 1 # pyright: ignore[reportAttributeAccessIssue]
189+
creator.add_item(si)
190+
191+
184192
def test_add_item_for_delete(tmp_path, html_file):
185193
fpath = tmp_path / "test.zim"
186194
local_path = pathlib.Path(tmp_path / "somefile.html")
@@ -480,6 +488,51 @@ def cb():
480488
assert Store.called is True
481489

482490

491+
def test_item_callbacks(tmp_path):
492+
fpath = tmp_path / "test.zim"
493+
494+
class Store:
495+
called = 0
496+
497+
def cb():
498+
Store.called += 1
499+
500+
with Creator(fpath, "").config_dev_metadata() as creator:
501+
creator.add_item_for(
502+
path="hello",
503+
content="hello",
504+
callbacks=[Callback(func=cb), Callback(func=cb)],
505+
)
506+
507+
assert Store.called == 2
508+
509+
class UnCallableCallback(Callback):
510+
@property
511+
def callable(self) -> bool:
512+
return False
513+
514+
with Creator(fpath, "").config_dev_metadata() as creator:
515+
# +2
516+
creator.add_item(
517+
StaticItem(path="hello", content="hello"),
518+
callbacks=[Callback(func=cb), Callback(func=cb)],
519+
)
520+
# + 0
521+
creator.add_item(StaticItem(path="hello2", content="hello"))
522+
# +1
523+
creator.add_item(
524+
StaticItem(path="hello3", content="hello"),
525+
callbacks=Callback(func=cb),
526+
)
527+
# + 0
528+
creator.add_item(
529+
StaticItem(path="hello4", content="hello"),
530+
callbacks=UnCallableCallback(func=cb),
531+
)
532+
533+
assert Store.called == 5
534+
535+
483536
def test_compess_hints(tmp_path, html_file):
484537
with Creator(tmp_path / "test.zim", "").config_dev_metadata() as creator:
485538
creator.add_item_for(

0 commit comments

Comments
 (0)