diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e66ff7..9339d29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + - Set up documentation using `mkdocs`, published on readthedocs.com (#186) +- `Archive.get_random_entry()` ## [3.6.0] - 2024-10-15 diff --git a/libzim/libwrapper.h b/libzim/libwrapper.h index 9d6bafd..2736ee0 100644 --- a/libzim/libwrapper.h +++ b/libzim/libwrapper.h @@ -144,6 +144,7 @@ class Archive : public Wrapper FORWARD(wrapper::Entry, getEntryByPath) FORWARD(wrapper::Entry, getEntryByTitle) FORWARD(wrapper::Entry, getMainEntry) + FORWARD(wrapper::Entry, getRandomEntry) FORWARD(wrapper::Item, getIllustrationItem) FORWARD(std::set, getIllustrationSizes) std::string getUuid() const diff --git a/libzim/libzim.pyx b/libzim/libzim.pyx index 72196da..c895f59 100644 --- a/libzim/libzim.pyx +++ b/libzim/libzim.pyx @@ -1101,6 +1101,21 @@ cdef class Archive: raise KeyError(str(e)) return Entry.from_entry(move(entry)) + def get_random_entry(self) -> Entry: + """Get a random `Entry`. + + Returns: + A random entry. + + Raises: + KeyError: If no valid random entry is found. + """ + try: + entry = move(self.c_archive.getRandomEntry()) + except RuntimeError as e: + raise KeyError(str(e)) + return Entry.from_entry(move(entry)) + @property def metadata_keys(self) -> List[str]: """List of Metadata keys present in this archive. diff --git a/libzim/reader.pyi b/libzim/reader.pyi index 46e6609..43cfc6e 100644 --- a/libzim/reader.pyi +++ b/libzim/reader.pyi @@ -41,6 +41,7 @@ class Archive: def get_entry_by_path(self, path: str) -> Entry: ... def has_entry_by_title(self, title: str) -> bool: ... def get_entry_by_title(self, title: str) -> Entry: ... + def get_random_entry(self) -> Entry: ... @property def metadata_keys(self) -> list[str]: ... def get_metadata_item(self, name: str) -> Item: ... diff --git a/libzim/zim.pxd b/libzim/zim.pxd index 84f4948..02aab2a 100644 --- a/libzim/zim.pxd +++ b/libzim/zim.pxd @@ -153,6 +153,7 @@ cdef extern from "libwrapper.h" namespace "wrapper": vector[string] getMetadataKeys() except + Entry getMainEntry() except + + Entry getRandomEntry() except + Item getIllustrationItem() except + Item getIllustrationItem(int size) except + size_type getEntryCount() except + diff --git a/tests/test_libzim_reader.py b/tests/test_libzim_reader.py index 28da539..54fa64b 100644 --- a/tests/test_libzim_reader.py +++ b/tests/test_libzim_reader.py @@ -9,7 +9,7 @@ import pytest import libzim.writer # pyright: ignore [reportMissingModuleSource] -from libzim.reader import Archive # pyright: ignore [reportMissingModuleSource] +from libzim.reader import Archive, Entry # pyright: ignore [reportMissingModuleSource] from libzim.search import Query, Searcher # pyright: ignore [reportMissingModuleSource] from libzim.suggestion import ( # pyright: ignore [reportMissingModuleSource] SuggestionSearcher, @@ -599,3 +599,19 @@ def filename(self): assert zim != Different(fpath1) assert zim == Sub(fpath1) assert zim != Sub2(fpath1) + + +def test_reader_get_random_entry(all_zims): + zim_1 = Archive(all_zims / "zimfile.zim") + + entry_1 = zim_1.get_random_entry() + entry_2 = zim_1.get_random_entry() + assert isinstance(entry_1, Entry) + assert isinstance(entry_2, Entry) + # this may occasionaly fail (1 chance over 129) + assert entry_1 != entry_2 + + # example.zim has no FRONT_ARTICLE (article_count=0): random cannot yield any result + zim_2 = Archive(all_zims / "example.zim") + with pytest.raises(KeyError): + zim_2.get_random_entry()