Skip to content

Commit 4a0d6b1

Browse files
committed
Move all python only code out of the pyx file.
The `libzim_wrapper` is created. It is "internal" and is in charge to wrap the c++ part. The public (python) code is move to `__init__.py`. It uses `libzim_wrapper` to provide functionalities to the user.
1 parent 45ad923 commit 4a0d6b1

File tree

7 files changed

+371
-378
lines changed

7 files changed

+371
-378
lines changed

libzim/__init__.py

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# This file is part of python-libzim
2+
# (see https://github.com/libzim/python-libzim)
3+
#
4+
# Copyright (c) 2020 Juan Diego Caballero <[email protected]>
5+
# Copyright (c) 2020 Matthieu Gautier <[email protected]>
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU General Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU General Public License
18+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
20+
21+
import libzim_wrapper
22+
23+
ZimBlob = libzim_wrapper.ZimBlob
24+
25+
from collections import defaultdict
26+
import datetime
27+
28+
__all__ = ["ZimArticle", "ZimCreator", "ZimBlob"]
29+
30+
class ZimArticle:
31+
def __init__(self):
32+
self._blob = None
33+
34+
def get_url(self):
35+
raise NotImplementedError
36+
37+
def get_title(self):
38+
raise NotImplementedError
39+
40+
def is_redirect(self):
41+
raise NotImplementedError
42+
43+
def get_mime_type(self):
44+
raise NotImplementedError
45+
46+
def get_filename(self):
47+
raise NotImplementedError
48+
49+
def should_compress(self):
50+
raise NotImplementedError
51+
52+
def should_index(self):
53+
raise NotImplementedError
54+
55+
def redirect_url(self):
56+
raise NotImplementedError
57+
58+
def _get_data(self):
59+
if self._blob is None:
60+
self._blob = self.get_data()
61+
return self._blob
62+
63+
def get_data(self):
64+
raise NotImplementedError
65+
66+
67+
class ZimMetadataArticle(ZimArticle):
68+
def __init__(self, url, metadata_content):
69+
ZimArticle.__init__(self)
70+
self.url = url
71+
self.metadata_content = metadata_content
72+
73+
def is_redirect(self):
74+
return False
75+
76+
def get_url(self):
77+
return f"M/{self.url}"
78+
79+
def get_title(self):
80+
return ""
81+
82+
def get_mime_type(self):
83+
return "text/plain"
84+
85+
def get_filename(self):
86+
return ""
87+
88+
def should_compress(self):
89+
return True
90+
91+
def should_index(self):
92+
return False
93+
94+
def get_data(self):
95+
return ZimBlob(self.metadata_content)
96+
97+
98+
MANDATORY_METADATA_KEYS =[
99+
"Name",
100+
"Title",
101+
"Creator",
102+
"Publisher",
103+
"Date",
104+
"Description",
105+
"Language"]
106+
107+
class ZimCreator:
108+
"""
109+
A class to represent a Zim Creator.
110+
111+
Attributes
112+
----------
113+
*c_creator : zim.ZimCreatorWrapper
114+
a pointer to the C++ Creator object
115+
_finalized : bool
116+
flag if the creator was finalized
117+
_filename : str
118+
Zim file path
119+
_main_page : str
120+
Zim file main page
121+
_index_language : str
122+
Zim file Index language
123+
_min_chunk_size : str
124+
Zim file minimum chunk size
125+
_article_counter
126+
Zim file article counter
127+
_metadata
128+
Zim file metadata
129+
"""
130+
131+
def __init__(self, filename, main_page, index_language, min_chunk_size):
132+
print(filename)
133+
self._creatorWrapper = libzim_wrapper.ZimCreator(
134+
filename,
135+
main_page,
136+
index_language,
137+
min_chunk_size)
138+
self.filename = filename
139+
self.main_page = main_page
140+
self.language = index_language
141+
self._metadata = {}
142+
self._article_counter = defaultdict(int)
143+
self.update_metadata(date=datetime.date.today(), language=index_language)
144+
145+
def __enter__(self):
146+
return self
147+
148+
def __exit__(self, *args):
149+
self.close()
150+
151+
def add_article(self, article):
152+
self._creatorWrapper.add_article(article)
153+
if not article.is_redirect():
154+
self._update_article_counter(article)
155+
156+
def _update_article_counter(self, article):
157+
# default dict update
158+
self._article_counter[article.get_mime_type().strip()] += 1
159+
160+
def mandatory_metadata_ok(self):
161+
"""Flag if mandatory metadata is complete and not empty"""
162+
metadata_item_ok = [k in self._metadata for k in MANDATORY_METADATA_KEYS]
163+
return all(metadata_item_ok)
164+
165+
166+
def update_metadata(self, **kwargs):
167+
"Updates article metadata"""
168+
# Converts python case to pascal case. example: long_description-> LongDescription
169+
pascalize = lambda keyword: "".join(keyword.title().split("_"))
170+
new_metadata = {pascalize(k): v for k, v in kwargs.items()}
171+
self._metadata.update(new_metadata)
172+
173+
174+
def write_metadata(self):
175+
for key, value in self._metadata.items():
176+
if key == "date" and isinstance(value, datetime.date):
177+
value = value.strftime("%Y-%m-%d")
178+
article = ZimMetadataArticle(key, value)
179+
self._creatorWrapper.add_article(article)
180+
181+
article = ZimMetadataArticle("Counter", self._get_counter_string())
182+
self._creatorWrapper.add_article(article)
183+
184+
def _get_counter_string(self):
185+
return ";".join(
186+
["%s=%s" % (k,v) for (k,v) in self._article_counter.items()]
187+
)
188+
189+
def close(self):
190+
self.write_metadata()
191+
self._creatorWrapper.finalize()
192+
193+
def __repr__(self):
194+
return f"ZimCreator(filename={self.filename})"

libzim/lib.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <Python.h>
2424
#include "lib.h"
2525

26-
#include "libzim_api.h"
26+
#include "libzim_wrapper_api.h"
2727

2828
#include <iostream>
2929
#include <zim/writer/url.h>
@@ -38,7 +38,7 @@
3838

3939
ZimArticleWrapper::ZimArticleWrapper(PyObject *obj) : m_obj(obj)
4040
{
41-
if (import_libzim())
41+
if (import_libzim_wrapper())
4242
{
4343
std::cerr << "Error executing import_libzim!\n";
4444
throw std::runtime_error("Error executing import_libzim");

0 commit comments

Comments
 (0)