Skip to content

Commit abf4c58

Browse files
authored
Add actions (#4)
1 parent 72d41d7 commit abf4c58

File tree

6 files changed

+173
-10
lines changed

6 files changed

+173
-10
lines changed

.github/workflows/ci-workflow.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Checks workflow
2+
3+
on: ['push', 'pull_request']
4+
5+
jobs:
6+
check-toc:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- name: Run
11+
run: make toc-check
12+
13+
release:
14+
needs: check-toc
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v2
19+
- name: Create epub
20+
uses: docker://pandoc/core:2.14
21+
with:
22+
args: --toc --toc-depth=6 -o questions.epub metadata.txt questions.md
23+
24+
- name: Get TAG
25+
if: startsWith(github.ref, 'refs/tags/')
26+
run: echo "TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
27+
- name: Write build number
28+
if: startsWith(github.ref, 'refs/tags/')
29+
run: sed -i "s/build 1/$TAG/g" metadata.txt
30+
- name: Test
31+
run: cat metadata.txt
32+
- name: Release
33+
if: startsWith(github.ref, 'refs/tags/')
34+
uses: softprops/action-gh-release@v1
35+
with:
36+
files: questions.epub

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
11
questions.epub: questions.md metadata.txt book_res/* attachments/* Makefile ## Generate epub book
22
pandoc --toc --toc-depth=6 -o questions.epub metadata.txt questions.md
3+
4+
.PHONY: toc
5+
toc: ## Generate TOC from questions.md
6+
python3 generate_toc.py
7+
8+
.PHONY: toc
9+
toc-check: ## Check that toc is actual
10+
python3 generate_toc.py --check

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525

2626
### Нашел ошибку/опечатку/бред в ответах или хочу добавить еще вопросов
2727

28-
Молодец, создавай PR. Не забудь добавить себя в [contributors.md](contributors.md)
28+
Молодец, создавай PR.
29+
30+
- После того как что-то изменил в [questions.md](questions.md) запусти `make toc` чтобы обновить [Список вопросов](#Список-вопросов)
31+
- Не забудь добавить себя в [metadata.txt](metadata.txt) в раздел `author`
2932

3033
### Не хочу читать в Markdown, хочу читать в электронной книге
3134

@@ -60,7 +63,7 @@
6063
+ [Что возвращает метод items](questions.md/#Что-возвращает-метод-items)
6164
+ [Как отсортировать список словарей по определенному полю](questions.md/#Как-отсортировать-список-словарей-по-определенному-полю)
6265
+ [Что может являться ключом словаря. Что не может. Почему](questions.md/#Что-может-являться-ключом-словаря-Что-не-может-Почему)
63-
+ [Есть два списка – ключи и значения. Как составить из них словарь](questions.md/#Есть-два-списка--ключи-и-значения-Как-составить-из-них-словарь)
66+
+ [Есть два списка – ключи и значения. Как составить из них словарь](questions.md/#Есть-два-списка--ключи-и-значения-Как-составить-из-них-словарь)
6467
+ [Как работает хэш-таблица](questions.md/#Как-работает-хэш-таблица)
6568
+ [Что такое коллизия](questions.md/#Что-такое-коллизия)
6669
+ [Где будет быстрее поиск, а где перебор и почему: dict, list, set, tuple](questions.md/#Где-будет-быстрее-поиск-а-где-перебор-и-почему-dict-list-set-tuple)
@@ -183,7 +186,7 @@
183186
+ [В чем отличие тредов от мультипроцессинга](questions.md/#В-чем-отличие-тредов-от-мультипроцессинга)
184187
+ [Какие задачи хорошо параллелятся, какие плохо](questions.md/#Какие-задачи-хорошо-параллелятся-какие-плохо)
185188
+ [Нужно посчитать 100 уравнений. Делать это в тредах или нет](questions.md/#Нужно-посчитать-100-уравнений-Делать-это-в-тредах-или-нет)
186-
+ [Треды в Питоне — это нативные треды или нет](questions.md/#Треды-в-Питоне-это-нативные-треды-или-нет)
189+
+ [Треды в Питоне — это нативные треды или нет](questions.md/#Треды-в-Питоне--это-нативные-треды-или-нет)
187190
+ [Что такое гринлеты. Общее понятие. Примеры реализаций](questions.md/#Что-такое-гринлеты-Общее-понятие-Примеры-реализаций)
188191
* [Какие варианты реализации шаблона Singleton на питоне](questions.md/#Какие-варианты-реализации-шаблона-Singleton-на-питоне)
189192
* [Какие вы знаете инструменты для проверки кодстайл](questions.md/#Какие-вы-знаете-инструменты-для-проверки-кодстайл)
@@ -199,7 +202,7 @@
199202
* [Опишите алгоритм работы CSRF middleware](questions.md/#Опишите-алгоритм-работы-CSRF-middleware)
200203
* [Что такое сигналы? Зачем нужны? Назовите основные](questions.md/#Что-такое-сигналы-Зачем-нужны-Назовите-основные)
201204
* [Как реализуется связь m2m на уровне базы данных](questions.md/#Как-реализуется-связь-m2m-на-уровне-базы-данных)
202-
* [Чем лучше отправлять форму — GET или POST](questions.md/#Чем-лучше-отправлять-форму--GET-или-POST)
205+
* [Чем лучше отправлять форму — GET или POST](questions.md/#Чем-лучше-отправлять-форму--GET-или-POST)
203206
* [Как работает Serializer в Django REST Framework](questions.md/#Как-работает-Serializer-в-Django-REST-Framework)
204207
* [Что такое Meta в классах Django и для чего нужен](questions.md/#Что-такое-Meta-в-классах-Django-и-для-чего-нужен)
205208
* [За что отвечает Meta в сериализаторе](questions.md/#За-что-отвечает-Meta-в-сериализаторе)
@@ -232,7 +235,7 @@
232235
+ [Наследование](questions.md/#Наследование)
233236
+ [Полиморфизм](questions.md/#Полиморфизм)
234237
+ [Абстракция](questions.md/#Абстракция)
235-
* [Какие принципы программирования вы знаете](questions.md/#Какиe-принципы-программирования-вы-знаете)
238+
* [Какие принципы программирования вы знаете](questions.md/#Какие-принципы-программирования-вы-знаете)
236239
+ [KISS](questions.md/#KISS)
237240
+ [DRY](questions.md/#DRY)
238241
+ [YAGNI](questions.md/#YAGNI)

contributors.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

generate_toc.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import dataclasses
2+
import re
3+
import sys
4+
from typing import List
5+
6+
7+
@dataclasses.dataclass()
8+
class Header:
9+
name: str
10+
level: int
11+
12+
@property
13+
def slug(self):
14+
text = self.name.replace(' ', '-')
15+
# single chars that are removed
16+
text = re.sub(r'[`~!@#$%^&*()+=<>?,./:;"\'|{}\[\]\\–—]', '', text)
17+
# CJK punctuations that are removed
18+
text = re.sub(r'[ 。?!,、;:“”【】()〔〕[]﹃﹄“”‘’﹁﹂—…-~《》〈〉「」]', '', text)
19+
return text
20+
21+
22+
class TOCMaker:
23+
def __init__(
24+
self,
25+
*,
26+
max_depth=6,
27+
link_prefix='',
28+
indentation_size=2,
29+
list_bullets=('-', '*', '+', '-'),
30+
header_class=Header,
31+
):
32+
self.max_depth = max_depth
33+
self.link_prefix = link_prefix
34+
self.indentation_size = indentation_size
35+
self.list_bullets = list_bullets
36+
self.header_class = header_class
37+
38+
def make(self, text):
39+
headers = self._collect_headers(text)
40+
return self._make_toc(headers)
41+
42+
def make_from_file(self, fp):
43+
return self.make(fp.read())
44+
45+
def _collect_headers(self, text):
46+
headers = []
47+
48+
code_blocks = 0
49+
for line in text.splitlines():
50+
line = line.strip()
51+
code_blocks += line.count('```') % 2
52+
if code_blocks % 2 == 0 and line.startswith('#'):
53+
header = self._parse_header_from_line(line)
54+
if header.level <= self.max_depth:
55+
headers.append(self._parse_header_from_line(line))
56+
57+
return headers
58+
59+
def _make_toc(self, headers: List[Header]):
60+
toc = []
61+
for header in headers:
62+
indentation = ' ' * ((header.level - 1) * self.indentation_size)
63+
bullet = self._get_bullet(header.level)
64+
toc.append(f'{indentation}{bullet} [{header.name}]({self.link_prefix}#{header.slug})')
65+
return '\n'.join(toc)
66+
67+
def _get_bullet(self, level):
68+
if level > len(self.list_bullets):
69+
return self.list_bullets[-1]
70+
return self.list_bullets[level - 1]
71+
72+
def _parse_header_from_line(self, line):
73+
level = 0
74+
name = ''
75+
for char in line:
76+
if char == '#':
77+
level += 1
78+
else:
79+
name = line[level + 1:].strip()
80+
break
81+
82+
return self.header_class(
83+
name=name,
84+
level=level
85+
)
86+
87+
88+
def paste_after(delimiter, content, text):
89+
result = []
90+
for line in text.splitlines():
91+
if line.strip() != delimiter:
92+
result.append(line)
93+
else:
94+
result.append(f'{delimiter}\n')
95+
result.append(f'{content}\n')
96+
return '\n'.join(result)
97+
98+
raise ValueError(f"Can't find delimiter '{delimiter}'")
99+
100+
101+
if __name__ == '__main__':
102+
with open('questions.md') as fp:
103+
maker = TOCMaker(link_prefix='questions.md/')
104+
toc = maker.make_from_file(fp)
105+
106+
with open('README.md', 'r') as fp:
107+
original = fp.read()
108+
changed = paste_after('<!-- toc -->', toc, original)
109+
110+
if '--check' in sys.argv:
111+
if original != changed:
112+
print('Error')
113+
sys.exit(1)
114+
else:
115+
with open('README.md', 'w') as fp:
116+
fp.write(changed)
117+
118+
print('Done')

metadata.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ title:
44
text: Вопросы для подготовки к Python Developer интервью
55
- type: edition
66
text: build 1
7-
creator:
8-
- role: author
9-
text: yakimka
7+
author:
8+
- yakimka <https://github.com/yakimka>
9+
- pavlenk0 <https://github.com/pavlenk0>
1010
toc-title: Содержание
1111
language: ru-RU
1212
stylesheet: book_res/style.css

0 commit comments

Comments
 (0)