chgksuite 0.25.0b4__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.0b4/chgksuite.egg-info → chgksuite-0.25.1}/PKG-INFO +1 -1
  2. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/common.py +4 -0
  3. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/pptx.py +68 -47
  4. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/telegram.py +8 -5
  5. chgksuite-0.25.1/chgksuite/version.py +1 -0
  6. {chgksuite-0.25.0b4 → chgksuite-0.25.1/chgksuite.egg-info}/PKG-INFO +1 -1
  7. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/history.md +7 -0
  8. chgksuite-0.25.0b4/chgksuite/version.py +0 -1
  9. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/LICENSE +0 -0
  10. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/MANIFEST.in +0 -0
  11. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/README.md +0 -0
  12. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/__init__.py +0 -0
  13. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/__main__.py +0 -0
  14. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/cli.py +0 -0
  15. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/__init__.py +0 -0
  16. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/chgksuite_parser.py +0 -0
  17. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/composer_common.py +0 -0
  18. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/db.py +0 -0
  19. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/docx.py +0 -0
  20. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/latex.py +0 -0
  21. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/lj.py +0 -0
  22. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/openquiz.py +0 -0
  23. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/reddit.py +0 -0
  24. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/stats.py +0 -0
  25. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/telegram_bot.py +0 -0
  26. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/composer/telegram_parser.py +0 -0
  27. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/parser.py +0 -0
  28. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/parser_db.py +0 -0
  29. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/cheader.tex +0 -0
  30. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/fix-unnumbered-sections.sty +0 -0
  31. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_by.toml +0 -0
  32. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_by_tar.toml +0 -0
  33. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_en.toml +0 -0
  34. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_kz_cyr.toml +0 -0
  35. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_ru.toml +0 -0
  36. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_sr.toml +0 -0
  37. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_ua.toml +0 -0
  38. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_uz.toml +0 -0
  39. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/labels_uz_cyr.toml +0 -0
  40. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/pptx_config.toml +0 -0
  41. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/regexes_by.json +0 -0
  42. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/regexes_en.json +0 -0
  43. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/regexes_kz_cyr.json +0 -0
  44. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/regexes_ru.json +0 -0
  45. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/regexes_sr.json +0 -0
  46. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/regexes_ua.json +0 -0
  47. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/regexes_uz_cyr.json +0 -0
  48. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/template.docx +0 -0
  49. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/template.pptx +0 -0
  50. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/template_shorin.pptx +0 -0
  51. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/resources/trello.json +0 -0
  52. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/trello.py +0 -0
  53. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/typotools.py +0 -0
  54. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite/vulture_whitelist.py +0 -0
  55. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite.egg-info/SOURCES.txt +0 -0
  56. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite.egg-info/dependency_links.txt +0 -0
  57. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite.egg-info/entry_points.txt +0 -0
  58. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite.egg-info/requires.txt +0 -0
  59. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/chgksuite.egg-info/top_level.txt +0 -0
  60. {chgksuite-0.25.0b4 → chgksuite-0.25.1}/setup.cfg +0 -0
  61. {chgksuite-0.25.0b4 → 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.0b4
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,12 @@ 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)
231
244
  if self.c["number_textbox"].get("bold"):
232
245
  qtf_r.font.bold = True
233
246
  if self.c["number_textbox"].get("color"):
@@ -278,6 +291,15 @@ class PptxExporter(BaseExporter):
278
291
  base_top = PptxInches(self.c["textbox"]["top"])
279
292
  base_width = PptxInches(self.c["textbox"]["width"])
280
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
281
303
  big_mode = (
282
304
  image["big"] and not self.c.get("text_is_duplicated") and allowbigimage
283
305
  )
@@ -390,9 +412,13 @@ class PptxExporter(BaseExporter):
390
412
  def process_question_text(self, q):
391
413
  image = self._get_image_from_4s(q["question"])
392
414
  handout = self._get_handout_from_4s(q["question"])
393
- 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:
394
420
  self.add_slide_with_image(image, number=self.number)
395
- elif handout:
421
+ elif handout and add_handout_on_separate_slide:
396
422
  self.add_slide_with_handout(handout, number=self.number)
397
423
  slide = self.prs.slides.add_slide(self.BLANK_SLIDE)
398
424
  text_is_duplicated = bool(self.c.get("text_is_duplicated"))
@@ -413,7 +439,7 @@ class PptxExporter(BaseExporter):
413
439
  fields.append("zachet")
414
440
  if self.c["add_comment"] and "comment" in q:
415
441
  fields.append("comment")
416
- if self.c["add_source"] and "source" in q:
442
+ if self.c.get("add_source") and "source" in q:
417
443
  fields.append("source")
418
444
  textbox = None
419
445
  coeff = 1
@@ -451,34 +477,29 @@ class PptxExporter(BaseExporter):
451
477
  p = self.init_paragraph(tf, size=self.c["force_text_size_answer"])
452
478
  else:
453
479
  p = self.init_paragraph(tf, text=text_for_size, coeff=coeff)
454
- r = p.add_run()
455
- r.text = f"{self.get_label(q, 'answer')}: "
480
+ r = self.add_run(p, f"{self.get_label(q, 'answer')}: ")
456
481
  r.font.bold = True
457
482
  self.pptx_format(
458
483
  self.pptx_process_text(q["answer"], strip_brackets=False), p, tf, slide
459
484
  )
460
485
  if q.get("zachet") and self.c.get("add_zachet"):
461
486
  zachet_text = self.pptx_process_text(q["zachet"], strip_brackets=False)
462
- r = p.add_run()
463
- r.text = f"\n{self.get_label(q, 'zachet')}: "
487
+ r = self.add_run(p, f"\n{self.get_label(q, 'zachet')}: ")
464
488
  r.font.bold = True
465
489
  self.pptx_format(zachet_text, p, tf, slide)
466
490
  if self.c["add_comment"] and "comment" in q:
467
491
  comment_text = self.pptx_process_text(q["comment"])
468
- r = p.add_run()
469
- r.text = f"\n{self.get_label(q, 'comment')}: "
492
+ r = self.add_run(p, f"\n{self.get_label(q, 'comment')}: ")
470
493
  r.font.bold = True
471
494
  self.pptx_format(comment_text, p, tf, slide)
472
- if self.c["add_source"] and "source" in q:
495
+ if self.c.get("add_source") and "source" in q:
473
496
  source_text = self.pptx_process_text(q["source"])
474
- r = p.add_run()
475
- r.text = f"\n{self.get_label(q, 'source')}: "
497
+ r = self.add_run(p, f"\n{self.get_label(q, 'source')}: ")
476
498
  r.font.bold = True
477
499
  self.pptx_format(source_text, p, tf, slide)
478
- if self.c["add_author"] and "author" in q:
500
+ if self.c.get("add_author") and "author" in q:
479
501
  author_text = self.pptx_process_text(q["author"])
480
- r = p.add_run()
481
- r.text = f"\n{self.get_label(q, 'author')}: "
502
+ r = self.add_run(p, f"\n{self.get_label(q, 'author')}: ")
482
503
  r.font.bold = True
483
504
  self.pptx_format(author_text, p, tf, slide)
484
505
 
@@ -510,7 +531,7 @@ class PptxExporter(BaseExporter):
510
531
  return element["size"]
511
532
  return self.c["text_size_grid"]["smallest"]
512
533
 
513
- 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):
514
535
  p = text_frame.paragraphs[0]
515
536
  p.font.name = self.c["font"]["name"]
516
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.0b4
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.0b4"
File without changes
File without changes
File without changes
File without changes
File without changes