chgksuite 0.26.1__tar.gz → 0.27.0b1__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.
- {chgksuite-0.26.1/chgksuite.egg-info → chgksuite-0.27.0b1}/PKG-INFO +6 -13
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/cli.py +12 -8
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/common.py +4 -1
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/composer_common.py +14 -5
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/docx.py +29 -8
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/openquiz.py +1 -1
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/pptx.py +2 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/telegram.py +2 -1
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/handouter/gen.py +11 -7
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/handouter/runner.py +10 -4
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/handouter/tex_internals.py +0 -11
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/parser.py +6 -9
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/parser_db.py +3 -4
- chgksuite-0.27.0b1/chgksuite/resources/labels_az.toml +22 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_by.toml +1 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_by_tar.toml +1 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_en.toml +1 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_kz_cyr.toml +1 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_ru.toml +1 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_sr.toml +1 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_ua.toml +1 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_uz.toml +0 -3
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/labels_uz_cyr.toml +1 -2
- chgksuite-0.27.0b1/chgksuite/resources/regexes_az.json +17 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/regexes_by.json +3 -2
- chgksuite-0.27.0b1/chgksuite/resources/regexes_by_tar.json +17 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/regexes_en.json +3 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/regexes_kz_cyr.json +3 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/regexes_ru.json +3 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/regexes_sr.json +3 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/regexes_ua.json +3 -2
- chgksuite-0.27.0b1/chgksuite/resources/regexes_uz.json +16 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/regexes_uz_cyr.json +3 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/trello.py +1 -1
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/typotools.py +5 -4
- chgksuite-0.27.0b1/chgksuite/version.py +1 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1/chgksuite.egg-info}/PKG-INFO +6 -13
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite.egg-info/SOURCES.txt +5 -2
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite.egg-info/requires.txt +1 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/history.md +7 -1
- chgksuite-0.27.0b1/pyproject.toml +75 -0
- chgksuite-0.26.1/chgksuite/composer/telegram_parser.py +0 -230
- chgksuite-0.26.1/chgksuite/version.py +0 -1
- chgksuite-0.26.1/setup.py +0 -66
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/LICENSE +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/MANIFEST.in +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/README.md +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/__init__.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/__main__.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/__init__.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/chgksuite_parser.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/db.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/latex.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/lj.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/reddit.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/stats.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/composer/telegram_bot.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/handouter/__init__.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/handouter/installer.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/handouter/pack.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/handouter/utils.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/cheader.tex +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/fix-unnumbered-sections.sty +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/pptx_config.toml +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/template.docx +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/template.pptx +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/resources/trello.json +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite/vulture_whitelist.py +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite.egg-info/dependency_links.txt +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite.egg-info/entry_points.txt +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/chgksuite.egg-info/top_level.txt +0 -0
- {chgksuite-0.26.1 → chgksuite-0.27.0b1}/setup.cfg +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chgksuite
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.27.0b1
|
|
4
4
|
Summary: A package for chgk automation
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Author-email: Alexander Pecheny <ap@pecheny.me>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/peczony/chgksuite
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
9
|
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Requires-Dist: beautifulsoup4
|
|
@@ -27,16 +27,9 @@ Requires-Dist: python-pptx
|
|
|
27
27
|
Requires-Dist: python-telegram-bot
|
|
28
28
|
Requires-Dist: requests
|
|
29
29
|
Requires-Dist: toml
|
|
30
|
+
Requires-Dist: urllib3>=2.6.2
|
|
30
31
|
Requires-Dist: watchdog
|
|
31
|
-
Dynamic: author
|
|
32
|
-
Dynamic: author-email
|
|
33
|
-
Dynamic: classifier
|
|
34
|
-
Dynamic: description
|
|
35
|
-
Dynamic: description-content-type
|
|
36
|
-
Dynamic: home-page
|
|
37
32
|
Dynamic: license-file
|
|
38
|
-
Dynamic: requires-dist
|
|
39
|
-
Dynamic: summary
|
|
40
33
|
|
|
41
34
|
**chgksuite** is an utility that helps chgk editors.
|
|
42
35
|
|
|
@@ -13,12 +13,14 @@ from chgksuite.common import (
|
|
|
13
13
|
)
|
|
14
14
|
from chgksuite.composer import gui_compose
|
|
15
15
|
from chgksuite.handouter.runner import gui_handouter
|
|
16
|
-
from chgksuite.handouter.tex_internals import GREYTEXT_LANGS
|
|
17
16
|
from chgksuite.parser import gui_parse
|
|
18
17
|
from chgksuite.trello import gui_trello
|
|
19
18
|
from chgksuite.version import __version__
|
|
20
19
|
|
|
21
|
-
LANGS = ["by", "by_tar", "en", "kz_cyr", "ru", "sr", "ua", "uz", "uz_cyr"] + [
|
|
20
|
+
LANGS = ["az", "by", "by_tar", "en", "kz_cyr", "ru", "sr", "ua", "uz", "uz_cyr"] + [
|
|
21
|
+
"custom"
|
|
22
|
+
]
|
|
23
|
+
HANDOUT_LANGS = [lang for lang in LANGS if lang != "custom"]
|
|
22
24
|
|
|
23
25
|
debug = False
|
|
24
26
|
|
|
@@ -889,10 +891,11 @@ class ArgparseBuilder:
|
|
|
889
891
|
)
|
|
890
892
|
self.add_argument(
|
|
891
893
|
cmdhandouts_run,
|
|
892
|
-
"--
|
|
894
|
+
"--language",
|
|
895
|
+
"-lang",
|
|
893
896
|
default="ru",
|
|
894
897
|
argtype="radiobutton",
|
|
895
|
-
choices=sorted(
|
|
898
|
+
choices=sorted(HANDOUT_LANGS),
|
|
896
899
|
help="language",
|
|
897
900
|
caption="Язык",
|
|
898
901
|
advanced=True,
|
|
@@ -1012,12 +1015,13 @@ class ArgparseBuilder:
|
|
|
1012
1015
|
)
|
|
1013
1016
|
self.add_argument(
|
|
1014
1017
|
cmdhandouts_generate,
|
|
1015
|
-
"--
|
|
1018
|
+
"--language",
|
|
1019
|
+
"-lang",
|
|
1016
1020
|
default="ru",
|
|
1017
1021
|
help="language",
|
|
1018
1022
|
caption="Язык",
|
|
1019
1023
|
argtype="radiobutton",
|
|
1020
|
-
choices=sorted(
|
|
1024
|
+
choices=sorted(HANDOUT_LANGS),
|
|
1021
1025
|
advanced=True,
|
|
1022
1026
|
)
|
|
1023
1027
|
self.add_argument(
|
|
@@ -1084,9 +1088,9 @@ def single_action(args, use_wrapper, resourcedir):
|
|
|
1084
1088
|
args.console_mode = True
|
|
1085
1089
|
|
|
1086
1090
|
if args.language in LANGS:
|
|
1091
|
+
args.regexes_file = os.path.join(resourcedir, f"regexes_{args.language}.json")
|
|
1087
1092
|
if args.action == "parse":
|
|
1088
|
-
|
|
1089
|
-
args.regexes = os.path.join(resourcedir, f"regexes_{regex_lang}.json")
|
|
1093
|
+
args.regexes = args.regexes_file
|
|
1090
1094
|
args.labels_file = os.path.join(resourcedir, f"labels_{args.language}.toml")
|
|
1091
1095
|
if not args.docx_template:
|
|
1092
1096
|
args.docx_template = os.path.join(resourcedir, "template.docx")
|
|
@@ -29,7 +29,10 @@ QUESTION_LABELS = [
|
|
|
29
29
|
"setcounter",
|
|
30
30
|
]
|
|
31
31
|
SEP = os.linesep
|
|
32
|
-
|
|
32
|
+
try:
|
|
33
|
+
ENC = sys.stdout.encoding or "utf8"
|
|
34
|
+
except AttributeError:
|
|
35
|
+
ENC = "utf8"
|
|
33
36
|
|
|
34
37
|
lastdir = os.path.join(os.path.dirname(os.path.abspath("__file__")), "lastdir")
|
|
35
38
|
|
|
@@ -59,8 +59,8 @@ def backtick_replace(el):
|
|
|
59
59
|
return el
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
def remove_accents_standalone(s,
|
|
63
|
-
hs =
|
|
62
|
+
def remove_accents_standalone(s, regexes):
|
|
63
|
+
hs = regexes["handout_short"]
|
|
64
64
|
re_hs = re.compile(f"\\[{hs}(.+?)\\]", flags=re.DOTALL)
|
|
65
65
|
replacements = {}
|
|
66
66
|
n_handouts = 0
|
|
@@ -413,6 +413,8 @@ class BaseExporter:
|
|
|
413
413
|
self.dir_kwargs = args[2]
|
|
414
414
|
with open(self.args.labels_file, encoding="utf8") as f:
|
|
415
415
|
self.labels = toml.load(f)
|
|
416
|
+
with open(self.args.regexes_file, encoding="utf8") as f:
|
|
417
|
+
self.regexes = json.load(f)
|
|
416
418
|
logger = kwargs.get("logger")
|
|
417
419
|
if logger:
|
|
418
420
|
self.logger = logger
|
|
@@ -451,10 +453,11 @@ class BaseExporter:
|
|
|
451
453
|
return self.labels["question_labels"][field]
|
|
452
454
|
|
|
453
455
|
def remove_square_brackets(self, s):
|
|
454
|
-
hs = self.
|
|
456
|
+
hs = self.regexes["handout_short"]
|
|
455
457
|
s = s.replace("\\[", "LEFTSQUAREBRACKET")
|
|
456
458
|
s = s.replace("\\]", "RIGHTSQUAREBRACKET")
|
|
457
|
-
|
|
459
|
+
# Use placeholder to preserve handout brackets during removal
|
|
460
|
+
s = re.sub(f"\\[{hs}(.+?)\\]", "{HANDOUT_PLACEHOLDER\\1}", s, flags=re.DOTALL)
|
|
458
461
|
i = 0
|
|
459
462
|
while "[" in s and "]" in s and i < 10:
|
|
460
463
|
s = re.sub(" *\\[.+?\\]", "", s, flags=re.DOTALL)
|
|
@@ -464,7 +467,13 @@ class BaseExporter:
|
|
|
464
467
|
sys.stderr.write(
|
|
465
468
|
f"Error replacing square brackets on question: {s}, retries exceeded\n"
|
|
466
469
|
)
|
|
467
|
-
|
|
470
|
+
# Restore handout brackets - get the original matched text from the placeholder
|
|
471
|
+
s = re.sub(
|
|
472
|
+
r"\{HANDOUT_PLACEHOLDER(.+?)\}",
|
|
473
|
+
lambda m: "[" + m.group(1) + "]",
|
|
474
|
+
s,
|
|
475
|
+
flags=re.DOTALL,
|
|
476
|
+
)
|
|
468
477
|
s = s.replace("LEFTSQUAREBRACKET", "[")
|
|
469
478
|
s = s.replace("RIGHTSQUAREBRACKET", "]")
|
|
470
479
|
return s
|
|
@@ -96,12 +96,13 @@ def get_label_standalone(
|
|
|
96
96
|
return labels["question_labels"][field]
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
def remove_square_brackets_standalone(s,
|
|
99
|
+
def remove_square_brackets_standalone(s, regexes):
|
|
100
100
|
"""Standalone version of remove_square_brackets"""
|
|
101
|
-
hs =
|
|
101
|
+
hs = regexes["handout_short"]
|
|
102
102
|
s = s.replace("\\[", "LEFTSQUAREBRACKET")
|
|
103
103
|
s = s.replace("\\]", "RIGHTSQUAREBRACKET")
|
|
104
|
-
|
|
104
|
+
# Use placeholder to preserve handout brackets during removal
|
|
105
|
+
s = re.sub(f"\\[{hs}(.+?)\\]", "{HANDOUT_PLACEHOLDER\\1}", s, flags=re.DOTALL)
|
|
105
106
|
i = 0
|
|
106
107
|
while "[" in s and "]" in s and i < 10:
|
|
107
108
|
s = re.sub(" *\\[.+?\\]", "", s, flags=re.DOTALL)
|
|
@@ -111,7 +112,13 @@ def remove_square_brackets_standalone(s, labels):
|
|
|
111
112
|
sys.stderr.write(
|
|
112
113
|
f"Error replacing square brackets on question: {s}, retries exceeded\n"
|
|
113
114
|
)
|
|
114
|
-
|
|
115
|
+
# Restore handout brackets - get the original matched text from the placeholder
|
|
116
|
+
s = re.sub(
|
|
117
|
+
r"\{HANDOUT_PLACEHOLDER(.+?)\}",
|
|
118
|
+
lambda m: "[" + m.group(1) + "]",
|
|
119
|
+
s,
|
|
120
|
+
flags=re.DOTALL,
|
|
121
|
+
)
|
|
115
122
|
s = s.replace("LEFTSQUAREBRACKET", "[")
|
|
116
123
|
s = s.replace("RIGHTSQUAREBRACKET", "]")
|
|
117
124
|
return s
|
|
@@ -140,6 +147,7 @@ def format_docx_element(
|
|
|
140
147
|
spoilers="none",
|
|
141
148
|
logger=None,
|
|
142
149
|
labels=None,
|
|
150
|
+
regexes=None,
|
|
143
151
|
language="ru",
|
|
144
152
|
remove_accents=False,
|
|
145
153
|
remove_brackets=False,
|
|
@@ -157,6 +165,7 @@ def format_docx_element(
|
|
|
157
165
|
spoilers: Spoiler handling mode ("none", "whiten", "dots", "pagebreak")
|
|
158
166
|
logger: Logger instance
|
|
159
167
|
labels: Labels dictionary
|
|
168
|
+
regexes: Regexes dictionary (for handout_short)
|
|
160
169
|
language: Language code
|
|
161
170
|
remove_accents: Whether to remove accents
|
|
162
171
|
remove_brackets: Whether to remove square brackets
|
|
@@ -176,6 +185,7 @@ def format_docx_element(
|
|
|
176
185
|
spoilers,
|
|
177
186
|
logger,
|
|
178
187
|
labels,
|
|
188
|
+
regexes,
|
|
179
189
|
language,
|
|
180
190
|
remove_accents,
|
|
181
191
|
remove_brackets,
|
|
@@ -194,6 +204,7 @@ def format_docx_element(
|
|
|
194
204
|
spoilers,
|
|
195
205
|
logger,
|
|
196
206
|
labels,
|
|
207
|
+
regexes,
|
|
197
208
|
language,
|
|
198
209
|
remove_accents,
|
|
199
210
|
remove_brackets,
|
|
@@ -213,6 +224,7 @@ def format_docx_element(
|
|
|
213
224
|
spoilers,
|
|
214
225
|
logger,
|
|
215
226
|
labels,
|
|
227
|
+
regexes,
|
|
216
228
|
language,
|
|
217
229
|
remove_accents,
|
|
218
230
|
remove_brackets,
|
|
@@ -223,10 +235,10 @@ def format_docx_element(
|
|
|
223
235
|
if isinstance(el, str):
|
|
224
236
|
logger.debug("parsing element {}:".format(log_wrap(el)))
|
|
225
237
|
|
|
226
|
-
if remove_accents and
|
|
227
|
-
el = remove_accents_standalone(el,
|
|
228
|
-
if remove_brackets and
|
|
229
|
-
el = remove_square_brackets_standalone(el,
|
|
238
|
+
if remove_accents and regexes:
|
|
239
|
+
el = remove_accents_standalone(el, regexes)
|
|
240
|
+
if remove_brackets and regexes:
|
|
241
|
+
el = remove_square_brackets_standalone(el, regexes)
|
|
230
242
|
else:
|
|
231
243
|
el = replace_escaped(el)
|
|
232
244
|
|
|
@@ -309,6 +321,7 @@ def add_question_to_docx(
|
|
|
309
321
|
doc,
|
|
310
322
|
question_data,
|
|
311
323
|
labels,
|
|
324
|
+
regexes=None,
|
|
312
325
|
qcount=None,
|
|
313
326
|
skip_qcount=False,
|
|
314
327
|
screen_mode=False,
|
|
@@ -329,6 +342,7 @@ def add_question_to_docx(
|
|
|
329
342
|
doc: docx Document object
|
|
330
343
|
question_data: Dictionary containing question data
|
|
331
344
|
labels: Labels dictionary
|
|
345
|
+
regexes: Regexes dictionary (for handout_short)
|
|
332
346
|
qcount: Current question count (will be incremented if not skip_qcount)
|
|
333
347
|
skip_qcount: Whether to skip incrementing question count
|
|
334
348
|
screen_mode: Whether to use screen mode formatting
|
|
@@ -392,6 +406,7 @@ def add_question_to_docx(
|
|
|
392
406
|
spoilers,
|
|
393
407
|
logger,
|
|
394
408
|
labels,
|
|
409
|
+
regexes,
|
|
395
410
|
language,
|
|
396
411
|
remove_accents=screen_mode,
|
|
397
412
|
remove_brackets=screen_mode,
|
|
@@ -411,6 +426,7 @@ def add_question_to_docx(
|
|
|
411
426
|
spoilers,
|
|
412
427
|
logger,
|
|
413
428
|
labels,
|
|
429
|
+
regexes,
|
|
414
430
|
language,
|
|
415
431
|
remove_accents=screen_mode,
|
|
416
432
|
remove_brackets=screen_mode,
|
|
@@ -453,6 +469,7 @@ def add_question_to_docx(
|
|
|
453
469
|
spoilers,
|
|
454
470
|
logger,
|
|
455
471
|
labels,
|
|
472
|
+
regexes,
|
|
456
473
|
language,
|
|
457
474
|
remove_accents=screen_mode,
|
|
458
475
|
replace_no_break_spaces=True,
|
|
@@ -481,6 +498,7 @@ def add_question_to_docx(
|
|
|
481
498
|
spoilers,
|
|
482
499
|
logger,
|
|
483
500
|
labels,
|
|
501
|
+
regexes,
|
|
484
502
|
language,
|
|
485
503
|
remove_accents=screen_mode,
|
|
486
504
|
remove_brackets=screen_mode,
|
|
@@ -514,6 +532,7 @@ class DocxExporter(BaseExporter):
|
|
|
514
532
|
spoilers=self.args.spoilers,
|
|
515
533
|
logger=self.logger,
|
|
516
534
|
labels=self.labels,
|
|
535
|
+
regexes=self.regexes,
|
|
517
536
|
language=self.args.language,
|
|
518
537
|
**kwargs,
|
|
519
538
|
)
|
|
@@ -528,6 +547,7 @@ class DocxExporter(BaseExporter):
|
|
|
528
547
|
spoilers=self.args.spoilers,
|
|
529
548
|
logger=self.logger,
|
|
530
549
|
labels=self.labels,
|
|
550
|
+
regexes=self.regexes,
|
|
531
551
|
language=self.args.language,
|
|
532
552
|
**kwargs,
|
|
533
553
|
)
|
|
@@ -542,6 +562,7 @@ class DocxExporter(BaseExporter):
|
|
|
542
562
|
self.doc,
|
|
543
563
|
element[1],
|
|
544
564
|
self.labels,
|
|
565
|
+
self.regexes,
|
|
545
566
|
self.qcount,
|
|
546
567
|
skip_qcount,
|
|
547
568
|
screen_mode,
|
|
@@ -71,7 +71,7 @@ class OpenquizExporter(BaseExporter):
|
|
|
71
71
|
)
|
|
72
72
|
while res.endswith("\n"):
|
|
73
73
|
res = res[:-1]
|
|
74
|
-
hs = self.
|
|
74
|
+
hs = self.regexes["handout_short"]
|
|
75
75
|
if images:
|
|
76
76
|
res = re.sub("\\[" + hs + "(.+?)\\]", "", s, flags=re.DOTALL)
|
|
77
77
|
res = res.strip()
|
|
@@ -121,13 +121,13 @@ class PptxExporter(BaseExporter):
|
|
|
121
121
|
replace_spaces=True,
|
|
122
122
|
do_not_remove_accents=False,
|
|
123
123
|
):
|
|
124
|
-
hs = self.
|
|
124
|
+
hs = self.regexes["handout_short"]
|
|
125
125
|
if isinstance(s, list):
|
|
126
126
|
for i in range(len(s)):
|
|
127
127
|
s[i] = self.pptx_process_text(s[i], image=image)
|
|
128
128
|
return s
|
|
129
129
|
if not (self.args.do_not_remove_accents or do_not_remove_accents):
|
|
130
|
-
s = remove_accents_standalone(s, self.
|
|
130
|
+
s = remove_accents_standalone(s, self.regexes)
|
|
131
131
|
if strip_brackets:
|
|
132
132
|
s = self.remove_square_brackets(s)
|
|
133
133
|
s = s.replace("]\n", "]\n\n")
|
|
@@ -6,6 +6,7 @@ import sqlite3
|
|
|
6
6
|
import tempfile
|
|
7
7
|
import time
|
|
8
8
|
import uuid
|
|
9
|
+
from typing import Optional, Union
|
|
9
10
|
|
|
10
11
|
import requests
|
|
11
12
|
import toml
|
|
@@ -247,7 +248,7 @@ class TelegramExporter(BaseExporter):
|
|
|
247
248
|
channel_id_str = channel_id_str[4:]
|
|
248
249
|
return f"https://t.me/c/{channel_id_str}/{message_id}"
|
|
249
250
|
|
|
250
|
-
def extract_id_from_link(self, link) -> int
|
|
251
|
+
def extract_id_from_link(self, link) -> Optional[Union[int, str]]:
|
|
251
252
|
"""
|
|
252
253
|
Extract channel or chat ID from a Telegram link.
|
|
253
254
|
Examples:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
import itertools
|
|
4
|
+
import json
|
|
4
5
|
import os
|
|
5
6
|
import re
|
|
6
7
|
from collections import defaultdict
|
|
@@ -53,13 +54,16 @@ def generate_handouts_list(handouts, output_dir, base_name, parsed):
|
|
|
53
54
|
|
|
54
55
|
def generate_handouts(args):
|
|
55
56
|
_, resourcedir = get_source_dirs()
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
toml.loads(read_file(os.path.join(resourcedir, f"labels_{args.language}.toml")))
|
|
58
|
+
with open(
|
|
59
|
+
os.path.join(resourcedir, f"regexes_{args.language}.json"), encoding="utf8"
|
|
60
|
+
) as f:
|
|
61
|
+
regexes = json.load(f)
|
|
62
|
+
handout_re_text = (
|
|
63
|
+
"\\[" + regexes["handout_short"] + ".+?:( |\n)(?P<handout_text>.+?)\\]"
|
|
58
64
|
)
|
|
59
65
|
handout_re = re.compile(
|
|
60
|
-
|
|
61
|
-
+ labels["question_labels"]["handout_short"]
|
|
62
|
-
+ ".+?:( |\n)(?P<handout_text>.+?)\\]",
|
|
66
|
+
handout_re_text,
|
|
63
67
|
flags=re.DOTALL,
|
|
64
68
|
)
|
|
65
69
|
|
|
@@ -82,9 +86,9 @@ def generate_handouts(args):
|
|
|
82
86
|
if img:
|
|
83
87
|
try:
|
|
84
88
|
parsed_img = parseimg(img[0][1])
|
|
85
|
-
except:
|
|
89
|
+
except Exception as e:
|
|
86
90
|
print(
|
|
87
|
-
f"Image file for question {q['number']} not found, add it by hand"
|
|
91
|
+
f"Image file for question {q['number']} not found, add it by hand (exception {type(e)} {e})"
|
|
88
92
|
)
|
|
89
93
|
continue
|
|
90
94
|
else:
|
|
@@ -5,15 +5,16 @@ import shutil
|
|
|
5
5
|
import subprocess
|
|
6
6
|
import time
|
|
7
7
|
|
|
8
|
+
import toml
|
|
8
9
|
from watchdog.events import FileSystemEventHandler
|
|
9
10
|
from watchdog.observers import Observer
|
|
10
11
|
|
|
12
|
+
from chgksuite.common import get_source_dirs
|
|
11
13
|
from chgksuite.handouter.gen import generate_handouts
|
|
12
14
|
from chgksuite.handouter.pack import pack_handouts
|
|
13
15
|
from chgksuite.handouter.installer import get_tectonic_path, install_tectonic
|
|
14
16
|
from chgksuite.handouter.tex_internals import (
|
|
15
17
|
GREYTEXT,
|
|
16
|
-
GREYTEXT_LANGS,
|
|
17
18
|
HEADER,
|
|
18
19
|
IMG,
|
|
19
20
|
IMGWIDTH,
|
|
@@ -29,6 +30,10 @@ class HandoutGenerator:
|
|
|
29
30
|
|
|
30
31
|
def __init__(self, args):
|
|
31
32
|
self.args = args
|
|
33
|
+
_, resourcedir = get_source_dirs()
|
|
34
|
+
self.labels = toml.loads(
|
|
35
|
+
read_file(os.path.join(resourcedir, f"labels_{args.language}.toml"))
|
|
36
|
+
)
|
|
32
37
|
self.blocks = [self.get_header()]
|
|
33
38
|
|
|
34
39
|
def get_header(self):
|
|
@@ -51,9 +56,10 @@ class HandoutGenerator:
|
|
|
51
56
|
return parse_handouts(contents)
|
|
52
57
|
|
|
53
58
|
def generate_for_question(self, question_num):
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
handout_text = self.labels["general"]["handout_for_question"].format(
|
|
60
|
+
question_num
|
|
56
61
|
)
|
|
62
|
+
return GREYTEXT.replace("<GREYTEXT>", handout_text)
|
|
57
63
|
|
|
58
64
|
def make_tikzbox(self, block):
|
|
59
65
|
if block.get("no_center"):
|
|
@@ -141,7 +147,7 @@ class HandoutGenerator:
|
|
|
141
147
|
|
|
142
148
|
def process_file(args, file_dir, bn):
|
|
143
149
|
tex_contents = HandoutGenerator(args).generate()
|
|
144
|
-
tex_path = os.path.join(file_dir, f"{bn}_{args.
|
|
150
|
+
tex_path = os.path.join(file_dir, f"{bn}_{args.language}.tex")
|
|
145
151
|
write_file(tex_path, tex_contents)
|
|
146
152
|
|
|
147
153
|
tectonic_path = get_tectonic_path()
|
|
@@ -20,17 +20,6 @@ HEADER = r"""
|
|
|
20
20
|
|
|
21
21
|
GREYTEXT = r"""{\fontsize{9pt}{11pt}\selectfont \textcolor{gray}{<GREYTEXT>}}"""
|
|
22
22
|
|
|
23
|
-
GREYTEXT_LANGS = {
|
|
24
|
-
"by": "Да пытаньня {}",
|
|
25
|
-
"en": "Handout for question {}",
|
|
26
|
-
"kz": "{}-сұрақтың үлестіру материалы",
|
|
27
|
-
"ro": "Material care urmează a fi distribuit pentru întrebarea {}",
|
|
28
|
-
"ru": "К вопросу {}",
|
|
29
|
-
"sr": "Materijal za deljenje uz pitanje {}",
|
|
30
|
-
"ua": "До запитання {}",
|
|
31
|
-
"uz": "{} саволга тарқатма материал",
|
|
32
|
-
}
|
|
33
|
-
|
|
34
23
|
TIKZBOX_START = r"""{<CENTERING>
|
|
35
24
|
"""
|
|
36
25
|
|
|
@@ -46,7 +46,7 @@ from chgksuite.parser_db import chgk_parse_db
|
|
|
46
46
|
from chgksuite.typotools import re_url
|
|
47
47
|
from chgksuite.typotools import remove_excessive_whitespace as rew
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
SEP = os.linesep
|
|
51
51
|
EDITORS = {
|
|
52
52
|
"win32": "notepad",
|
|
@@ -327,7 +327,7 @@ class ChgkParser:
|
|
|
327
327
|
regex,
|
|
328
328
|
regexes[regex].search(self.remove_formatting(st[i][1])).start(0),
|
|
329
329
|
)
|
|
330
|
-
for regex in set(regexes) - {"number", "date2"}
|
|
330
|
+
for regex in set(regexes) - {"number", "date2", "handout_short"}
|
|
331
331
|
if regexes[regex].search(self.remove_formatting(st[i][1]))
|
|
332
332
|
}
|
|
333
333
|
|
|
@@ -566,8 +566,8 @@ class ChgkParser:
|
|
|
566
566
|
# hack for https://gitlab.com/peczony/chgksuite/-/issues/23; TODO: make less hacky
|
|
567
567
|
for i, element in enumerate(self.structure):
|
|
568
568
|
if (
|
|
569
|
-
"
|
|
570
|
-
or "
|
|
569
|
+
"Дуплет." in element[1].split()
|
|
570
|
+
or "Блиц." in element[1].split()
|
|
571
571
|
and element[0] != "question"
|
|
572
572
|
and (i == 0 or self.structure[i - 1][0] != "question")
|
|
573
573
|
):
|
|
@@ -688,12 +688,9 @@ class ChgkParser:
|
|
|
688
688
|
except Exception as e:
|
|
689
689
|
num = None
|
|
690
690
|
sys.stderr.write(
|
|
691
|
-
f"exception at setting number: {type(e)} {e}\n"
|
|
691
|
+
f"exception at setting number: {type(e)} {e}\nQuestion: {element[1]}\n"
|
|
692
692
|
)
|
|
693
|
-
if (
|
|
694
|
-
num is None
|
|
695
|
-
or num and not num.group("number")
|
|
696
|
-
) and (
|
|
693
|
+
if (num is None or num and not num.group("number")) and (
|
|
697
694
|
("нулевой вопрос" in element[1].lower())
|
|
698
695
|
or ("разминочный вопрос" in element[1].lower())
|
|
699
696
|
):
|
|
@@ -128,7 +128,7 @@ def t_ANSWER(t):
|
|
|
128
128
|
t.lexer.text = ""
|
|
129
129
|
if t.lexer.question["answer"]:
|
|
130
130
|
logger.warning(
|
|
131
|
-
"Bad format: several Answer fields.
|
|
131
|
+
"Bad format: several Answer fields. Previous Answer was: '%s'",
|
|
132
132
|
t.lexer.question["answer"],
|
|
133
133
|
)
|
|
134
134
|
|
|
@@ -151,7 +151,7 @@ def t_COMMENT(t):
|
|
|
151
151
|
t.lexer.text = ""
|
|
152
152
|
if t.lexer.question["comment"]:
|
|
153
153
|
logger.warning(
|
|
154
|
-
"Bad format: several Comment fields.
|
|
154
|
+
"Bad format: several Comment fields. Previous Comment was: '%s'",
|
|
155
155
|
t.lexer.question["comment"],
|
|
156
156
|
)
|
|
157
157
|
|
|
@@ -162,7 +162,7 @@ def t_SOURCE(t):
|
|
|
162
162
|
t.lexer.text = ""
|
|
163
163
|
if t.lexer.question["source"]:
|
|
164
164
|
logger.warning(
|
|
165
|
-
"Bad format: several Source fields.
|
|
165
|
+
"Bad format: several Source fields. Previous Source was: '%s'",
|
|
166
166
|
t.lexer.question["source"],
|
|
167
167
|
)
|
|
168
168
|
|
|
@@ -417,7 +417,6 @@ def replace_handouts(match_handout):
|
|
|
417
417
|
|
|
418
418
|
|
|
419
419
|
def chgk_parse_db(text, debug=False, logger=False):
|
|
420
|
-
|
|
421
420
|
if not logger:
|
|
422
421
|
logger = init_logger("parser_db", debug=debug)
|
|
423
422
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[question_labels]
|
|
2
|
+
question = "Sual"
|
|
3
|
+
answer = "Cavab"
|
|
4
|
+
zachet = "Sayılma meyarı"
|
|
5
|
+
nezachet = "Sayılmır"
|
|
6
|
+
comment = "Şərh"
|
|
7
|
+
source = "Mənbə"
|
|
8
|
+
sources = "Mənbələr"
|
|
9
|
+
author = "Müəllif"
|
|
10
|
+
authors = "Müəlliflər"
|
|
11
|
+
handout = "Paylama materialı"
|
|
12
|
+
|
|
13
|
+
[general]
|
|
14
|
+
section = "Tur"
|
|
15
|
+
editor = "Redaktor"
|
|
16
|
+
date = "Tarix"
|
|
17
|
+
questions_in_comments = "Suallar şərh bölməsindədir."
|
|
18
|
+
general_impressions_caption = "Ümumi təəssüratlar"
|
|
19
|
+
handout_for_question = "Paylama materialı sual {} üçün"
|
|
20
|
+
general_impressions_text = "Paket barədə ümumi təəssüratlar — bu posun altına şərh kimi yazın."
|
|
21
|
+
right_answers_for_stats = "Doğru cavablar"
|
|
22
|
+
cf_image = "Şəklə baxın"
|
|
@@ -9,7 +9,6 @@ sources = "Крыніцы"
|
|
|
9
9
|
author = "Аўтар"
|
|
10
10
|
authors = "Аўтары"
|
|
11
11
|
handout = "Раздаткавы матэрыял"
|
|
12
|
-
handout_short = "Раздат"
|
|
13
12
|
|
|
14
13
|
[general]
|
|
15
14
|
section = "Тур"
|
|
@@ -19,4 +18,4 @@ questions_in_comments = "Пытанні ў каментарах."
|
|
|
19
18
|
handout_for_question = "Раздаткавы матэрыял да пытання {}"
|
|
20
19
|
general_impressions_caption = "Агульныя ўражанні"
|
|
21
20
|
general_impressions_text = "Агульныя ўражанні ад пакета — у каментарах да гэтага паста."
|
|
22
|
-
right_answers_for_stats = "Правільных адказаў"
|
|
21
|
+
right_answers_for_stats = "Правільных адказаў"
|
|
@@ -9,7 +9,6 @@ sources = "Крыніцы"
|
|
|
9
9
|
author = "Аўтар"
|
|
10
10
|
authors = "Аўтары"
|
|
11
11
|
handout = "Раздаткавы матэрыял"
|
|
12
|
-
handout_short = "Раздат"
|
|
13
12
|
|
|
14
13
|
[general]
|
|
15
14
|
section = "Тур"
|
|
@@ -19,4 +18,4 @@ questions_in_comments = "Пытаньні ў каментарыях."
|
|
|
19
18
|
handout_for_question = "Раздатачны матэрыял да пытаньня {}"
|
|
20
19
|
general_impressions_caption = "Агульныя ўражаньні"
|
|
21
20
|
general_impressions_text = "Агульныя ўражаньні ад пакета — у каментарыях да гэтага паста."
|
|
22
|
-
right_answers_for_stats = "Правільных адказаў"
|
|
21
|
+
right_answers_for_stats = "Правільных адказаў"
|
|
@@ -9,7 +9,6 @@ sources = "Sources"
|
|
|
9
9
|
author = "Author"
|
|
10
10
|
authors = "Authors"
|
|
11
11
|
handout = "Handout"
|
|
12
|
-
handout_short = "Handout"
|
|
13
12
|
|
|
14
13
|
[general]
|
|
15
14
|
section = "Block"
|
|
@@ -19,4 +18,4 @@ questions_in_comments = "Questions are in the comments."
|
|
|
19
18
|
handout_for_question = "Handout for question {}"
|
|
20
19
|
general_impressions_caption = "General impression"
|
|
21
20
|
general_impressions_text = "Please share your general impression of the packet in the comments to this post."
|
|
22
|
-
right_answers_for_stats = "Correct answers"
|
|
21
|
+
right_answers_for_stats = "Correct answers"
|
|
@@ -9,7 +9,6 @@ sources = "Дереккөздер"
|
|
|
9
9
|
author = "Автор"
|
|
10
10
|
authors = "Авторлар"
|
|
11
11
|
handout = "Үлестіру материалы"
|
|
12
|
-
handout_short = "Материал"
|
|
13
12
|
|
|
14
13
|
[general]
|
|
15
14
|
section = "Тур"
|
|
@@ -20,4 +19,4 @@ general_impressions_caption = "Жалпы әсер"
|
|
|
20
19
|
handout_for_question = "{}-сұрақтың үлестіру материалы"
|
|
21
20
|
general_impressions_text = "Пакеттен алған жалпы әсер — осы пост астындағы комментарийлерде."
|
|
22
21
|
right_answers_for_stats = "Алған сұрақтар"
|
|
23
|
-
cf_image = "суретті қараңыз"
|
|
22
|
+
cf_image = "суретті қараңыз"
|
|
@@ -9,7 +9,6 @@ sources = "Источники"
|
|
|
9
9
|
author = "Автор"
|
|
10
10
|
authors = "Авторы"
|
|
11
11
|
handout = "Раздаточный материал"
|
|
12
|
-
handout_short = "Раздат"
|
|
13
12
|
|
|
14
13
|
[general]
|
|
15
14
|
section = "Тур"
|
|
@@ -20,4 +19,4 @@ general_impressions_caption = "Общие впечатления"
|
|
|
20
19
|
handout_for_question = "Раздаточный материал к вопросу {}"
|
|
21
20
|
general_impressions_text = "Общее впечатление от пакета — в комментариях к этому посту."
|
|
22
21
|
right_answers_for_stats = "Взятия"
|
|
23
|
-
cf_image = "см. изображение"
|
|
22
|
+
cf_image = "см. изображение"
|
|
@@ -9,7 +9,6 @@ sources = "Izvori"
|
|
|
9
9
|
author = "Autor"
|
|
10
10
|
authors = "Autori"
|
|
11
11
|
handout = "Materijal za deljenje"
|
|
12
|
-
handout_short = "Podeljeno"
|
|
13
12
|
|
|
14
13
|
[general]
|
|
15
14
|
section = "Runda"
|
|
@@ -20,4 +19,4 @@ general_impressions_caption = "Opšti utisci"
|
|
|
20
19
|
handout_for_question = "Materijal za deljenje uz pitanje {}"
|
|
21
20
|
general_impressions_text = "Opšti utisak od paketa — u komentarima na ovu objavu."
|
|
22
21
|
right_answers_for_stats = "Pogodak"
|
|
23
|
-
cf_image = "vidi sliku"
|
|
22
|
+
cf_image = "vidi sliku"
|