chgksuite 0.24.3__py3-none-any.whl → 0.25.0__py3-none-any.whl

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/common.py CHANGED
@@ -224,6 +224,8 @@ def xlsx_to_results(xlsx_file_path):
224
224
  res_by_tour = defaultdict(lambda: defaultdict(list))
225
225
  tour_len = defaultdict(lambda: 0)
226
226
  for row in sheet.iter_rows(values_only=True):
227
+ if not any(x for x in row):
228
+ continue
227
229
  if first:
228
230
  assert row[1] == "Название"
229
231
  if row[3] == "Тур":
@@ -233,6 +235,8 @@ def xlsx_to_results(xlsx_file_path):
233
235
  first = False
234
236
  continue
235
237
  team_id = row[0]
238
+ if not tryint(team_id):
239
+ continue
236
240
  team_name = row[1]
237
241
  if table_type == "tour":
238
242
  tour = row[3]
@@ -5,10 +5,11 @@ import re
5
5
  import toml
6
6
  from pptx import Presentation
7
7
  from pptx.dml.color import RGBColor
8
+ from pptx.enum.text import MSO_AUTO_SIZE, MSO_VERTICAL_ANCHOR, PP_ALIGN
8
9
  from pptx.util import Inches as PptxInches
9
10
  from pptx.util import Pt as PptxPt
10
11
 
11
- from chgksuite.common import log_wrap, replace_escaped
12
+ from chgksuite.common import log_wrap, replace_escaped, tryint
12
13
  from chgksuite.composer.composer_common import BaseExporter, backtick_replace, parseimg
13
14
 
14
15
 
@@ -130,6 +131,14 @@ class PptxExporter(BaseExporter):
130
131
  s = s.strip()
131
132
  return s
132
133
 
134
+ def apply_vertical_alignment_if_needed(self, text_frame):
135
+ align = self.c["textbox"].get("vertical_align")
136
+ if align:
137
+ text_frame.auto_size = MSO_AUTO_SIZE.NONE
138
+ text_frame.margin_top = 0
139
+ text_frame.margin_bottom = 0
140
+ text_frame.vertical_anchor = getattr(MSO_VERTICAL_ANCHOR, align.upper())
141
+
133
142
  def _process_block(self, block):
134
143
  section = [x for x in block if x[0] == "section"]
135
144
  editor = [x for x in block if x[0] == "editor"]
@@ -139,6 +148,7 @@ class PptxExporter(BaseExporter):
139
148
  slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
140
149
  textbox = self.get_textbox(slide)
141
150
  tf = textbox.text_frame
151
+ self.apply_vertical_alignment_if_needed(tf)
142
152
  tf.word_wrap = True
143
153
  text_for_size = (
144
154
  (self.recursive_join([x[1] for x in section]) or "")
@@ -150,10 +160,16 @@ class PptxExporter(BaseExporter):
150
160
  p = self.init_paragraph(tf, text=text_for_size)
151
161
  add_line_break = False
152
162
  if section:
153
- r = p.add_run()
154
- r.text = self._replace_no_break(self.pptx_process_text(section[0][1]))
155
- r.font.size = PptxPt(self.c["text_size_grid"]["section"])
156
- add_line_break = True
163
+ if self.c.get("tour_as_question_number"):
164
+ txt = self.pptx_process_text(section[0][1])
165
+ if self.c.get("tour_as_question_number") == "caps":
166
+ txt = txt.upper()
167
+ self.set_question_number(slide, number=txt)
168
+ else:
169
+ r = p.add_run()
170
+ r.text = self._replace_no_break(self.pptx_process_text(section[0][1]))
171
+ r.font.size = PptxPt(self.c["text_size_grid"]["section"])
172
+ add_line_break = True
157
173
  if editor:
158
174
  r = p.add_run()
159
175
  r.text = self._replace_no_break(
@@ -206,10 +222,18 @@ class PptxExporter(BaseExporter):
206
222
  qntextbox = self.get_textbox_qnumber(slide)
207
223
  qtf = qntextbox.text_frame
208
224
  qtf_p = self.init_paragraph(qtf)
225
+ if self.c["number_textbox"].get("align"):
226
+ qtf_p.alignment = getattr(PP_ALIGN, self.c["number_textbox"]["align"].upper())
209
227
  qtf_r = qtf_p.add_run()
228
+ if self.c.get("question_number_format") == "caps" and tryint(number):
229
+ number = f"ВОПРОС {number}"
210
230
  qtf_r.text = number
231
+ if self.c["number_textbox"].get("bold"):
232
+ qtf_r.font.bold = True
211
233
  if self.c["number_textbox"].get("color"):
212
234
  qtf_r.font.color.rgb = RGBColor(*self.c["number_textbox"]["color"])
235
+ if self.c["number_textbox"].get("font_size"):
236
+ qtf_r.font.size = PptxPt(self.c["number_textbox"]["font_size"])
213
237
 
214
238
  def _get_handout_from_4s(self, text):
215
239
  if isinstance(text, list):
@@ -336,10 +360,14 @@ class PptxExporter(BaseExporter):
336
360
  image, slide, allowbigimage=allowbigimage
337
361
  )
338
362
  tf = textbox.text_frame
363
+ self.apply_vertical_alignment_if_needed(tf)
339
364
  tf.word_wrap = True
340
365
  self.set_question_number(slide, self.number)
341
366
  question_text = self.pptx_process_text(q["question"], image=image)
342
- p = self.init_paragraph(tf, text=question_text, coeff=coeff)
367
+ if self.c.get("force_text_size_question"):
368
+ p = self.init_paragraph(tf, size=self.c["force_text_size_question"])
369
+ else:
370
+ p = self.init_paragraph(tf, text=question_text, coeff=coeff)
343
371
  self.pptx_format(question_text, p, tf, slide)
344
372
 
345
373
  def recursive_join(self, s):
@@ -352,13 +380,12 @@ class PptxExporter(BaseExporter):
352
380
  slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
353
381
  textbox = self.get_textbox(slide)
354
382
  tf = textbox.text_frame
383
+ self.apply_vertical_alignment_if_needed(tf)
355
384
  tf.word_wrap = True
356
385
  if number is not None:
357
386
  self.set_question_number(slide, number)
358
387
  p = self.init_paragraph(tf, text=handout)
359
- self.pptx_format(
360
- self.pptx_process_text(handout), p, tf, slide
361
- )
388
+ self.pptx_format(self.pptx_process_text(handout), p, tf, slide)
362
389
 
363
390
  def process_question_text(self, q):
364
391
  image = self._get_image_from_4s(q["question"])
@@ -375,31 +402,19 @@ class PptxExporter(BaseExporter):
375
402
  if image and image["big"] and text_is_duplicated:
376
403
  self.add_slide_with_image(image, number=self.number)
377
404
 
378
- def process_question(self, q):
379
- if "number" not in q:
380
- self.qcount += 1
381
- if "setcounter" in q:
382
- self.qcount = int(q["setcounter"])
383
- self.number = str(self.qcount if "number" not in q else q["number"])
384
-
385
- if isinstance(q["question"], list):
386
- for i in range(len(q["question"][1])):
387
- qn = copy.deepcopy(q)
388
- qn["question"][1] = q["question"][1][: i + 1]
389
- self.process_question_text(qn)
405
+ def add_answer_slide(self, q):
406
+ slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
407
+ if self.c.get("override_answer_caption"):
408
+ self.set_question_number(slide, self.c["override_answer_caption"])
390
409
  else:
391
- self.process_question_text(q)
392
-
393
- if self.c["add_plug"]:
394
- slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
395
410
  self.set_question_number(slide, self.number)
396
- slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
397
- self.set_question_number(slide, self.number)
398
411
  fields = ["answer"]
399
412
  if q.get("zachet") and self.c.get("add_zachet"):
400
413
  fields.append("zachet")
401
414
  if self.c["add_comment"] and "comment" in q:
402
415
  fields.append("comment")
416
+ if self.c["add_source"] and "source" in q:
417
+ fields.append("source")
403
418
  textbox = None
404
419
  coeff = 1
405
420
  for field in fields:
@@ -410,6 +425,7 @@ class PptxExporter(BaseExporter):
410
425
  if not textbox:
411
426
  textbox = self.get_textbox(slide)
412
427
  tf = textbox.text_frame
428
+ self.apply_vertical_alignment_if_needed(tf)
413
429
  tf.word_wrap = True
414
430
 
415
431
  text_for_size = self.recursive_join(
@@ -423,7 +439,18 @@ class PptxExporter(BaseExporter):
423
439
  text_for_size += "\n" + self.recursive_join(
424
440
  self.pptx_process_text(q["comment"])
425
441
  )
426
- p = self.init_paragraph(tf, text=text_for_size, coeff=coeff)
442
+ if q.get("source") and self.c.get("add_source"):
443
+ text_for_size += "\n" + self.recursive_join(
444
+ self.pptx_process_text(q["source"])
445
+ )
446
+ if q.get("author") and self.c.get("add_author"):
447
+ text_for_size += "\n" + self.recursive_join(
448
+ self.pptx_process_text(q["author"])
449
+ )
450
+ if self.c.get("force_text_size_answer"):
451
+ p = self.init_paragraph(tf, size=self.c["force_text_size_answer"])
452
+ else:
453
+ p = self.init_paragraph(tf, text=text_for_size, coeff=coeff)
427
454
  r = p.add_run()
428
455
  r.text = f"{self.get_label(q, 'answer')}: "
429
456
  r.font.bold = True
@@ -442,6 +469,38 @@ class PptxExporter(BaseExporter):
442
469
  r.text = f"\n{self.get_label(q, 'comment')}: "
443
470
  r.font.bold = True
444
471
  self.pptx_format(comment_text, p, tf, slide)
472
+ if self.c["add_source"] and "source" in q:
473
+ source_text = self.pptx_process_text(q["source"])
474
+ r = p.add_run()
475
+ r.text = f"\n{self.get_label(q, 'source')}: "
476
+ r.font.bold = True
477
+ self.pptx_format(source_text, p, tf, slide)
478
+ if self.c["add_author"] and "author" in q:
479
+ author_text = self.pptx_process_text(q["author"])
480
+ r = p.add_run()
481
+ r.text = f"\n{self.get_label(q, 'author')}: "
482
+ r.font.bold = True
483
+ self.pptx_format(author_text, p, tf, slide)
484
+
485
+ def process_question(self, q):
486
+ if "number" not in q:
487
+ self.qcount += 1
488
+ if "setcounter" in q:
489
+ self.qcount = int(q["setcounter"])
490
+ self.number = str(self.qcount if "number" not in q else q["number"])
491
+
492
+ if isinstance(q["question"], list):
493
+ for i in range(len(q["question"][1])):
494
+ qn = copy.deepcopy(q)
495
+ qn["question"][1] = q["question"][1][: i + 1]
496
+ self.process_question_text(qn)
497
+ else:
498
+ self.process_question_text(q)
499
+
500
+ if self.c["add_plug"]:
501
+ slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
502
+ self.set_question_number(slide, self.number)
503
+ self.add_answer_slide(q)
445
504
 
446
505
  def determine_size(self, text, coeff=1):
447
506
  text = self.recursive_join(text)
@@ -451,13 +510,16 @@ class PptxExporter(BaseExporter):
451
510
  return element["size"]
452
511
  return self.c["text_size_grid"]["smallest"]
453
512
 
454
- def init_paragraph(self, text_frame, text=None, coeff=1):
513
+ def init_paragraph(self, text_frame, text=None, coeff=1, size=None):
455
514
  p = text_frame.paragraphs[0]
456
515
  p.font.name = self.c["font"]["name"]
457
- size = self.c["text_size_grid"]["default"]
458
- if text:
459
- size = self.determine_size(text, coeff=coeff)
460
- p.font.size = PptxPt(size)
516
+ if size:
517
+ _size = size
518
+ else:
519
+ _size = self.c["text_size_grid"]["default"]
520
+ if text:
521
+ _size = self.determine_size(text, coeff=coeff)
522
+ p.font.size = PptxPt(_size)
461
523
  return p
462
524
 
463
525
  def export(self, outfilename):
chgksuite/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.24.3"
1
+ __version__ = "0.25.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chgksuite
3
- Version: 0.24.3
3
+ Version: 0.25.0
4
4
  Summary: A package for chgk automation
5
5
  Home-page: https://gitlab.com/peczony/chgksuite
6
6
  Author: Alexander Pecheny
@@ -1,12 +1,12 @@
1
1
  chgksuite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  chgksuite/__main__.py,sha256=0-_jfloveTW3SZYW5XEagbyaHKGCiDhGNgcLxsT_dMs,140
3
3
  chgksuite/cli.py,sha256=8YoHWfc-wv6gdYMPH3X8HxV9SG70S7M6IQqavJaBXV4,31990
4
- chgksuite/common.py,sha256=FkEntLcVTApjLtTFTDf2QiMOath05i322wcmJIFjztQ,11093
4
+ chgksuite/common.py,sha256=VkOhoBA_P3qY5VgtvfrBjOsm5uVNL2s2Th2AhGB2pg8,11207
5
5
  chgksuite/parser.py,sha256=AVNeTUgv0aGHsxWunV_7bM4Ul2hbDslkzqg0dU49lic,37285
6
6
  chgksuite/parser_db.py,sha256=W1--OcDnx18mehH1T2ISHu3Saeq-9mqHo-xJopNySXI,11135
7
7
  chgksuite/trello.py,sha256=BG1Qb_W7Uu4o3Mfc_tK71ElU8ysdSplGlj_sAKfvUn4,14730
8
8
  chgksuite/typotools.py,sha256=Jdk65Wn_bXqpQtOT7PkBZyD2ZG1MBeeZFPMzcHEPkf4,12771
9
- chgksuite/version.py,sha256=FVT3zgMnGxhctio1D7Bj2hvIqrqQQ-a9tvDQYKSSekk,23
9
+ chgksuite/version.py,sha256=Mu4JbSLl5nr-J2figk5hmW2mrw4skf_oeIzxbnpcgwY,23
10
10
  chgksuite/vulture_whitelist.py,sha256=P__p_X0zt10ivddIf81uyxsobV14vFg8uS2lt4foYpc,3582
11
11
  chgksuite/composer/__init__.py,sha256=MAOVZIYXmZmD6nNQSo9DueV6b5RgxF7_HGeLvsAhMJs,6490
12
12
  chgksuite/composer/chgksuite_parser.py,sha256=MFcLUWbccMqo3OYEuaAIA0loEvWM_PNS9vR7c1z_c60,8843
@@ -16,7 +16,7 @@ chgksuite/composer/docx.py,sha256=5MASXACM-ztWrr3VdO8HZ-W-hWWQ5TY1jXMsCQIufGc,18
16
16
  chgksuite/composer/latex.py,sha256=WtLdUICxeX4_5vHEJRF0YhFLpTsOUwBkQFunQS488FA,9248
17
17
  chgksuite/composer/lj.py,sha256=nty3Zs3N1H0gNK378U04aAHo71_5cABhCM1Mm9jiUEA,15213
18
18
  chgksuite/composer/openquiz.py,sha256=4adZewvRXpZhKrh9H4epKoMMDhmki9US55-Q0LcpZW0,7019
19
- chgksuite/composer/pptx.py,sha256=lmLld5CCNfndmLwWz2rRqZFyPIUxl0Dvk6wO1jW_c5s,19116
19
+ chgksuite/composer/pptx.py,sha256=P4BewZj7TCiTM5atXxD1qvgW6GDWArp3NfwBN-7ytjg,22143
20
20
  chgksuite/composer/reddit.py,sha256=-Eg4CqMHhyGGfCteVwdQdtE1pfUXQ42XcP5OYUrBXmo,3878
21
21
  chgksuite/composer/stats.py,sha256=GbraSrjaZ8Mc2URs5aGAsI4ekboAKzlJJOqsbe96ELA,3995
22
22
  chgksuite/composer/telegram.py,sha256=H65LS79JZ3aCcqeq_SrnUU4E4yro1f-EZxCM3IrIyyQ,46526
@@ -45,9 +45,9 @@ chgksuite/resources/template.docx,sha256=Do29TAsg3YbH0rRSaXhVzKEoh4pwXkklW_idWA3
45
45
  chgksuite/resources/template.pptx,sha256=hEFWqE-yYpwZ8ejrMCJIPEyoMT3eDqaqtiEeQ7I4fyk,29777
46
46
  chgksuite/resources/template_shorin.pptx,sha256=hEFWqE-yYpwZ8ejrMCJIPEyoMT3eDqaqtiEeQ7I4fyk,29777
47
47
  chgksuite/resources/trello.json,sha256=M5Q9JR-AAJF1u16YtNAxDX-7c7VoVTXuq4POTqYvq8o,555
48
- chgksuite-0.24.3.dist-info/licenses/LICENSE,sha256=_a1yfntuPmctLsuiE_08xMSORuCfGS8X5hQph2U_PUw,1081
49
- chgksuite-0.24.3.dist-info/METADATA,sha256=WLpNUNLKen1BwBbn0w5MTDg7WhVyPUmwIZnPt81eFp8,1294
50
- chgksuite-0.24.3.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
51
- chgksuite-0.24.3.dist-info/entry_points.txt,sha256=lqjX6ULQZGDt0rgouTXBuwEPiwKkDQkSiNsT877A_Jg,54
52
- chgksuite-0.24.3.dist-info/top_level.txt,sha256=cSWiRBOGZW9nIO6Rv1IrEfwPgV2ZWs87QV9wPXeBGqM,10
53
- chgksuite-0.24.3.dist-info/RECORD,,
48
+ chgksuite-0.25.0.dist-info/licenses/LICENSE,sha256=_a1yfntuPmctLsuiE_08xMSORuCfGS8X5hQph2U_PUw,1081
49
+ chgksuite-0.25.0.dist-info/METADATA,sha256=ueTN4kr6BEoh8PvfvlbFTRfaWY5Lf7QBYvJQmONLZ3M,1294
50
+ chgksuite-0.25.0.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
51
+ chgksuite-0.25.0.dist-info/entry_points.txt,sha256=lqjX6ULQZGDt0rgouTXBuwEPiwKkDQkSiNsT877A_Jg,54
52
+ chgksuite-0.25.0.dist-info/top_level.txt,sha256=cSWiRBOGZW9nIO6Rv1IrEfwPgV2ZWs87QV9wPXeBGqM,10
53
+ chgksuite-0.25.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.0)
2
+ Generator: setuptools (80.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5