chgksuite 0.25.0b3__tar.gz → 0.25.1__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.
Files changed (61) hide show
  1. {chgksuite-0.25.0b3/chgksuite.egg-info → chgksuite-0.25.1}/PKG-INFO +1 -1
  2. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/common.py +4 -0
  3. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/pptx.py +70 -47
  4. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/telegram.py +8 -5
  5. chgksuite-0.25.1/chgksuite/version.py +1 -0
  6. {chgksuite-0.25.0b3 → chgksuite-0.25.1/chgksuite.egg-info}/PKG-INFO +1 -1
  7. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/history.md +7 -0
  8. chgksuite-0.25.0b3/chgksuite/version.py +0 -1
  9. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/LICENSE +0 -0
  10. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/MANIFEST.in +0 -0
  11. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/README.md +0 -0
  12. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/__init__.py +0 -0
  13. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/__main__.py +0 -0
  14. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/cli.py +0 -0
  15. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/__init__.py +0 -0
  16. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/chgksuite_parser.py +0 -0
  17. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/composer_common.py +0 -0
  18. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/db.py +0 -0
  19. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/docx.py +0 -0
  20. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/latex.py +0 -0
  21. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/lj.py +0 -0
  22. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/openquiz.py +0 -0
  23. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/reddit.py +0 -0
  24. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/stats.py +0 -0
  25. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/telegram_bot.py +0 -0
  26. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/composer/telegram_parser.py +0 -0
  27. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/parser.py +0 -0
  28. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/parser_db.py +0 -0
  29. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/cheader.tex +0 -0
  30. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/fix-unnumbered-sections.sty +0 -0
  31. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_by.toml +0 -0
  32. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_by_tar.toml +0 -0
  33. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_en.toml +0 -0
  34. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_kz_cyr.toml +0 -0
  35. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_ru.toml +0 -0
  36. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_sr.toml +0 -0
  37. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_ua.toml +0 -0
  38. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_uz.toml +0 -0
  39. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/labels_uz_cyr.toml +0 -0
  40. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/pptx_config.toml +0 -0
  41. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/regexes_by.json +0 -0
  42. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/regexes_en.json +0 -0
  43. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/regexes_kz_cyr.json +0 -0
  44. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/regexes_ru.json +0 -0
  45. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/regexes_sr.json +0 -0
  46. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/regexes_ua.json +0 -0
  47. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/regexes_uz_cyr.json +0 -0
  48. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/template.docx +0 -0
  49. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/template.pptx +0 -0
  50. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/template_shorin.pptx +0 -0
  51. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/resources/trello.json +0 -0
  52. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/trello.py +0 -0
  53. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/typotools.py +0 -0
  54. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite/vulture_whitelist.py +0 -0
  55. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite.egg-info/SOURCES.txt +0 -0
  56. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite.egg-info/dependency_links.txt +0 -0
  57. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite.egg-info/entry_points.txt +0 -0
  58. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite.egg-info/requires.txt +0 -0
  59. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/chgksuite.egg-info/top_level.txt +0 -0
  60. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/setup.cfg +0 -0
  61. {chgksuite-0.25.0b3 → chgksuite-0.25.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chgksuite
3
- Version: 0.25.0b3
3
+ Version: 0.25.1
4
4
  Summary: A package for chgk automation
5
5
  Home-page: https://gitlab.com/peczony/chgksuite
6
6
  Author: Alexander Pecheny
@@ -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]
@@ -3,15 +3,15 @@ import os
3
3
  import re
4
4
 
5
5
  import toml
6
+
7
+ from chgksuite.common import log_wrap, replace_escaped, tryint
8
+ from chgksuite.composer.composer_common import BaseExporter, backtick_replace, parseimg
6
9
  from pptx import Presentation
7
10
  from pptx.dml.color import RGBColor
8
11
  from pptx.enum.text import MSO_AUTO_SIZE, MSO_VERTICAL_ANCHOR, PP_ALIGN
9
12
  from pptx.util import Inches as PptxInches
10
13
  from pptx.util import Pt as PptxPt
11
14
 
12
- from chgksuite.common import log_wrap, replace_escaped, tryint
13
- from chgksuite.composer.composer_common import BaseExporter, backtick_replace, parseimg
14
-
15
15
 
16
16
  class PptxExporter(BaseExporter):
17
17
  def __init__(self, *args, **kwargs):
@@ -48,6 +48,15 @@ class PptxExporter(BaseExporter):
48
48
  textbox = slide.shapes.add_textbox(left, top, width, height)
49
49
  return textbox
50
50
 
51
+ def add_run(self, para, text, color=None):
52
+ r = para.add_run()
53
+ r.text = text
54
+ if color is None:
55
+ color = self.c["textbox"].get("color")
56
+ if color:
57
+ r.font.color.rgb = RGBColor(*color)
58
+ return r
59
+
51
60
  def pptx_format(self, el, para, tf, slide, replace_spaces=True):
52
61
  def r_sp(text):
53
62
  if replace_spaces:
@@ -60,15 +69,13 @@ class PptxExporter(BaseExporter):
60
69
  licount = 0
61
70
  for li in el[1]:
62
71
  licount += 1
63
- r = para.add_run()
64
- r.text = "\n{}. ".format(licount)
72
+ self.add_run(para, "\n{}. ".format(licount))
65
73
  self.pptx_format(li, para, tf, slide)
66
74
  else:
67
75
  licount = 0
68
76
  for li in el:
69
77
  licount += 1
70
- r = para.add_run()
71
- r.text = "\n{}. ".format(licount)
78
+ self.add_run(para, "\n{}. ".format(licount))
72
79
  self.pptx_format(li, para, tf, slide)
73
80
 
74
81
  if isinstance(el, str):
@@ -77,23 +84,20 @@ class PptxExporter(BaseExporter):
77
84
 
78
85
  for run in self.parse_4s_elem(el):
79
86
  if run[0] == "screen":
80
- r = para.add_run()
81
- r.text = r_sp(run[1]["for_screen"])
87
+ self.add_run(para, r_sp(run[1]["for_screen"]))
82
88
 
83
89
  elif run[0] == "linebreak":
84
- r = para.add_run("\n")
90
+ self.add_run(para, "\n")
85
91
 
86
92
  elif run[0] == "strike":
87
- r = para.add_run()
88
- r.text = r_sp(run[1])
93
+ r = self.add_run(para, r_sp(run[1]))
89
94
  r.font.strike = True # TODO: doesn't work as of 2023-12-24, cf. https://github.com/scanny/python-pptx/issues/339
90
95
 
91
96
  elif run[0] == "img":
92
97
  pass # image processing is moved to other places
93
98
 
94
99
  else:
95
- r = para.add_run()
96
- r.text = r_sp(run[1])
100
+ r = self.add_run(para, r_sp(run[1]))
97
101
  if "italic" in run[0]:
98
102
  r.font.italic = True
99
103
  if "bold" in run[0]:
@@ -166,25 +170,30 @@ class PptxExporter(BaseExporter):
166
170
  txt = txt.upper()
167
171
  self.set_question_number(slide, number=txt)
168
172
  else:
169
- r = p.add_run()
170
- r.text = self._replace_no_break(self.pptx_process_text(section[0][1]))
173
+ r = self.add_run(
174
+ p, self._replace_no_break(self.pptx_process_text(section[0][1]))
175
+ )
171
176
  r.font.size = PptxPt(self.c["text_size_grid"]["section"])
172
177
  add_line_break = True
173
178
  if editor:
174
- r = p.add_run()
175
- r.text = self._replace_no_break(
176
- ("\n" if add_line_break else "")
177
- + self.pptx_process_text(editor[0][1])
178
- + "\n"
179
+ r = self.add_run(
180
+ p,
181
+ self._replace_no_break(
182
+ ("\n" if add_line_break else "")
183
+ + self.pptx_process_text(editor[0][1])
184
+ + "\n"
185
+ ),
179
186
  )
180
187
  add_line_break = True
181
188
  if meta:
182
189
  for element in meta:
183
- r = p.add_run()
184
- r.text = self._replace_no_break(
185
- ("\n" if add_line_break else "")
186
- + self.pptx_process_text(element[1])
187
- + "\n"
190
+ r = self.add_run(
191
+ p,
192
+ self._replace_no_break(
193
+ ("\n" if add_line_break else "")
194
+ + self.pptx_process_text(element[1])
195
+ + "\n"
196
+ ),
188
197
  )
189
198
  add_line_break = True
190
199
 
@@ -211,8 +220,11 @@ class PptxExporter(BaseExporter):
211
220
  title = slide.shapes.title
212
221
  title.text = title_text[0][1]
213
222
  if date_text:
214
- subtitle = slide.placeholders[1]
215
- subtitle.text = date_text[0][1]
223
+ try:
224
+ subtitle = slide.placeholders[1]
225
+ subtitle.text = date_text[0][1]
226
+ except KeyError:
227
+ pass
216
228
  for block in (editor_block, section_block):
217
229
  self._process_block(block)
218
230
 
@@ -223,11 +235,14 @@ class PptxExporter(BaseExporter):
223
235
  qtf = qntextbox.text_frame
224
236
  qtf_p = self.init_paragraph(qtf)
225
237
  if self.c["number_textbox"].get("align"):
226
- qtf_p.alignment = getattr(PP_ALIGN, self.c["number_textbox"]["align"].upper())
227
- qtf_r = qtf_p.add_run()
238
+ qtf_p.alignment = getattr(
239
+ PP_ALIGN, self.c["number_textbox"]["align"].upper()
240
+ )
228
241
  if self.c.get("question_number_format") == "caps" and tryint(number):
229
242
  number = f"ВОПРОС {number}"
230
- qtf_r.text = number
243
+ qtf_r = self.add_run(qtf_p, number)
244
+ if self.c["number_textbox"].get("bold"):
245
+ qtf_r.font.bold = True
231
246
  if self.c["number_textbox"].get("color"):
232
247
  qtf_r.font.color.rgb = RGBColor(*self.c["number_textbox"]["color"])
233
248
  if self.c["number_textbox"].get("font_size"):
@@ -276,6 +291,15 @@ class PptxExporter(BaseExporter):
276
291
  base_top = PptxInches(self.c["textbox"]["top"])
277
292
  base_width = PptxInches(self.c["textbox"]["width"])
278
293
  base_height = PptxInches(self.c["textbox"]["height"])
294
+ if self.c.get("disable_autolayout"):
295
+ slide.shapes.add_picture(
296
+ image["imgfile"],
297
+ left=base_left,
298
+ top=base_top,
299
+ width=img_base_width,
300
+ height=img_base_height,
301
+ )
302
+ return self.get_textbox(slide), 1
279
303
  big_mode = (
280
304
  image["big"] and not self.c.get("text_is_duplicated") and allowbigimage
281
305
  )
@@ -388,9 +412,13 @@ class PptxExporter(BaseExporter):
388
412
  def process_question_text(self, q):
389
413
  image = self._get_image_from_4s(q["question"])
390
414
  handout = self._get_handout_from_4s(q["question"])
391
- if image:
415
+ add_handout_on_separate_slide = self.c.get("add_handout_on_separate_slide")
416
+ add_handout_on_separate_slide = (
417
+ add_handout_on_separate_slide is None or add_handout_on_separate_slide
418
+ )
419
+ if image and add_handout_on_separate_slide:
392
420
  self.add_slide_with_image(image, number=self.number)
393
- elif handout:
421
+ elif handout and add_handout_on_separate_slide:
394
422
  self.add_slide_with_handout(handout, number=self.number)
395
423
  slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
396
424
  text_is_duplicated = bool(self.c.get("text_is_duplicated"))
@@ -411,7 +439,7 @@ class PptxExporter(BaseExporter):
411
439
  fields.append("zachet")
412
440
  if self.c["add_comment"] and "comment" in q:
413
441
  fields.append("comment")
414
- if self.c["add_source"] and "source" in q:
442
+ if self.c.get("add_source") and "source" in q:
415
443
  fields.append("source")
416
444
  textbox = None
417
445
  coeff = 1
@@ -449,34 +477,29 @@ class PptxExporter(BaseExporter):
449
477
  p = self.init_paragraph(tf, size=self.c["force_text_size_answer"])
450
478
  else:
451
479
  p = self.init_paragraph(tf, text=text_for_size, coeff=coeff)
452
- r = p.add_run()
453
- r.text = f"{self.get_label(q, 'answer')}: "
480
+ r = self.add_run(p, f"{self.get_label(q, 'answer')}: ")
454
481
  r.font.bold = True
455
482
  self.pptx_format(
456
483
  self.pptx_process_text(q["answer"], strip_brackets=False), p, tf, slide
457
484
  )
458
485
  if q.get("zachet") and self.c.get("add_zachet"):
459
486
  zachet_text = self.pptx_process_text(q["zachet"], strip_brackets=False)
460
- r = p.add_run()
461
- r.text = f"\n{self.get_label(q, 'zachet')}: "
487
+ r = self.add_run(p, f"\n{self.get_label(q, 'zachet')}: ")
462
488
  r.font.bold = True
463
489
  self.pptx_format(zachet_text, p, tf, slide)
464
490
  if self.c["add_comment"] and "comment" in q:
465
491
  comment_text = self.pptx_process_text(q["comment"])
466
- r = p.add_run()
467
- r.text = f"\n{self.get_label(q, 'comment')}: "
492
+ r = self.add_run(p, f"\n{self.get_label(q, 'comment')}: ")
468
493
  r.font.bold = True
469
494
  self.pptx_format(comment_text, p, tf, slide)
470
- if self.c["add_source"] and "source" in q:
495
+ if self.c.get("add_source") and "source" in q:
471
496
  source_text = self.pptx_process_text(q["source"])
472
- r = p.add_run()
473
- r.text = f"\n{self.get_label(q, 'source')}: "
497
+ r = self.add_run(p, f"\n{self.get_label(q, 'source')}: ")
474
498
  r.font.bold = True
475
499
  self.pptx_format(source_text, p, tf, slide)
476
- if self.c["add_author"] and "author" in q:
500
+ if self.c.get("add_author") and "author" in q:
477
501
  author_text = self.pptx_process_text(q["author"])
478
- r = p.add_run()
479
- r.text = f"\n{self.get_label(q, 'author')}: "
502
+ r = self.add_run(p, f"\n{self.get_label(q, 'author')}: ")
480
503
  r.font.bold = True
481
504
  self.pptx_format(author_text, p, tf, slide)
482
505
 
@@ -508,7 +531,7 @@ class PptxExporter(BaseExporter):
508
531
  return element["size"]
509
532
  return self.c["text_size_grid"]["smallest"]
510
533
 
511
- def init_paragraph(self, text_frame, text=None, coeff=1, size=None):
534
+ def init_paragraph(self, text_frame, text=None, coeff=1, size=None, color=None):
512
535
  p = text_frame.paragraphs[0]
513
536
  p.font.name = self.c["font"]["name"]
514
537
  if size:
@@ -852,7 +852,7 @@ class TelegramExporter(BaseExporter):
852
852
 
853
853
  # Wait for a forwarded message with channel information
854
854
  channel_id = self.wait_for_forwarded_message(
855
- entity_type="channel", check_type=True, string_id=channel_result
855
+ entity_type="channel", check_type=True
856
856
  )
857
857
  if channel_id:
858
858
  self.save_username(channel_result, channel_id)
@@ -875,7 +875,7 @@ class TelegramExporter(BaseExporter):
875
875
 
876
876
  # Wait for a forwarded message with chat information
877
877
  chat_id = self.wait_for_forwarded_message(
878
- entity_type="chat", check_type=False, string_id=chat_result
878
+ entity_type="chat", check_type=False
879
879
  )
880
880
  if not chat_id:
881
881
  self.logger.error("Failed to get chat ID from forwarded message")
@@ -891,7 +891,6 @@ class TelegramExporter(BaseExporter):
891
891
  entity_type="chat",
892
892
  check_type=False,
893
893
  add_msg=error_msg,
894
- string_id=chat_result,
895
894
  )
896
895
  if chat_id:
897
896
  self.save_username(chat_result, chat_id)
@@ -1117,11 +1116,15 @@ class TelegramExporter(BaseExporter):
1117
1116
 
1118
1117
  # Look for a forwarded message in recent messages
1119
1118
  cursor = self.db_conn.cursor()
1119
+ if self.created_at:
1120
+ threshold = "'" + self.created_at + "'"
1121
+ else:
1122
+ threshold = "datetime('now', '-2 minutes')"
1120
1123
  cursor.execute(
1121
- """
1124
+ f"""
1122
1125
  SELECT raw_data, created_at
1123
1126
  FROM messages
1124
- WHERE created_at > datetime('now', '-2 minutes')
1127
+ WHERE created_at > {threshold}
1125
1128
  ORDER BY created_at DESC
1126
1129
  """
1127
1130
  )
@@ -0,0 +1 @@
1
+ __version__ = "0.25.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chgksuite
3
- Version: 0.25.0b3
3
+ Version: 0.25.1
4
4
  Summary: A package for chgk automation
5
5
  Home-page: https://gitlab.com/peczony/chgksuite
6
6
  Author: Alexander Pecheny
@@ -1,5 +1,12 @@
1
1
  # What’s new
2
2
 
3
+ ## v0.25.1
4
+ - Исправлен баг выкладывания пакета в телеграм
5
+
6
+ ## v0.25.0
7
+ - Адаптация к новому формату выходных таблиц турнирного сайта
8
+ - Улучшения выгрузки PPTX
9
+
3
10
  ## v0.24.0
4
11
  - Постинг в телеграм теперь происходит не через клиент, а через бота (подробнее можно прочитать в документации: https://chgksuite.pecheny.me/telegram/)
5
12
  - При невозможности распарсить табличку в вордовском файле теперь выдаётся предупреждение об этом (раньше программа просто падала)
@@ -1 +0,0 @@
1
- __version__ = "0.25.0b3"
File without changes
File without changes
File without changes
File without changes
File without changes