mirror of
https://github.com/yakimka/python_interview_questions.git
synced 2025-12-16 19:17:04 +03:00
Add actions (#4)
This commit is contained in:
36
.github/workflows/ci-workflow.yml
vendored
Normal file
36
.github/workflows/ci-workflow.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Checks workflow
|
||||
|
||||
on: ['push', 'pull_request']
|
||||
|
||||
jobs:
|
||||
check-toc:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run
|
||||
run: make toc-check
|
||||
|
||||
release:
|
||||
needs: check-toc
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Create epub
|
||||
uses: docker://pandoc/core:2.14
|
||||
with:
|
||||
args: --toc --toc-depth=6 -o questions.epub metadata.txt questions.md
|
||||
|
||||
- name: Get TAG
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: echo "TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
|
||||
- name: Write build number
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: sed -i "s/build 1/$TAG/g" metadata.txt
|
||||
- name: Test
|
||||
run: cat metadata.txt
|
||||
- name: Release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: questions.epub
|
||||
8
Makefile
8
Makefile
@@ -1,2 +1,10 @@
|
||||
questions.epub: questions.md metadata.txt book_res/* attachments/* Makefile ## Generate epub book
|
||||
pandoc --toc --toc-depth=6 -o questions.epub metadata.txt questions.md
|
||||
|
||||
.PHONY: toc
|
||||
toc: ## Generate TOC from questions.md
|
||||
python3 generate_toc.py
|
||||
|
||||
.PHONY: toc
|
||||
toc-check: ## Check that toc is actual
|
||||
python3 generate_toc.py --check
|
||||
|
||||
13
README.md
13
README.md
@@ -25,7 +25,10 @@
|
||||
|
||||
### Нашел ошибку/опечатку/бред в ответах или хочу добавить еще вопросов
|
||||
|
||||
Молодец, создавай PR. Не забудь добавить себя в [contributors.md](contributors.md)
|
||||
Молодец, создавай PR.
|
||||
|
||||
- После того как что-то изменил в [questions.md](questions.md) запусти `make toc` чтобы обновить [Список вопросов](#Список-вопросов)
|
||||
- Не забудь добавить себя в [metadata.txt](metadata.txt) в раздел `author`
|
||||
|
||||
### Не хочу читать в Markdown, хочу читать в электронной книге
|
||||
|
||||
@@ -60,7 +63,7 @@
|
||||
+ [Что возвращает метод items](questions.md/#Что-возвращает-метод-items)
|
||||
+ [Как отсортировать список словарей по определенному полю](questions.md/#Как-отсортировать-список-словарей-по-определенному-полю)
|
||||
+ [Что может являться ключом словаря. Что не может. Почему](questions.md/#Что-может-являться-ключом-словаря-Что-не-может-Почему)
|
||||
+ [Есть два списка – ключи и значения. Как составить из них словарь](questions.md/#Есть-два-списка-–-ключи-и-значения-Как-составить-из-них-словарь)
|
||||
+ [Есть два списка – ключи и значения. Как составить из них словарь](questions.md/#Есть-два-списка--ключи-и-значения-Как-составить-из-них-словарь)
|
||||
+ [Как работает хэш-таблица](questions.md/#Как-работает-хэш-таблица)
|
||||
+ [Что такое коллизия](questions.md/#Что-такое-коллизия)
|
||||
+ [Где будет быстрее поиск, а где перебор и почему: dict, list, set, tuple](questions.md/#Где-будет-быстрее-поиск-а-где-перебор-и-почему-dict-list-set-tuple)
|
||||
@@ -183,7 +186,7 @@
|
||||
+ [В чем отличие тредов от мультипроцессинга](questions.md/#В-чем-отличие-тредов-от-мультипроцессинга)
|
||||
+ [Какие задачи хорошо параллелятся, какие плохо](questions.md/#Какие-задачи-хорошо-параллелятся-какие-плохо)
|
||||
+ [Нужно посчитать 100 уравнений. Делать это в тредах или нет](questions.md/#Нужно-посчитать-100-уравнений-Делать-это-в-тредах-или-нет)
|
||||
+ [Треды в Питоне — это нативные треды или нет](questions.md/#Треды-в-Питоне-—это-нативные-треды-или-нет)
|
||||
+ [Треды в Питоне — это нативные треды или нет](questions.md/#Треды-в-Питоне--это-нативные-треды-или-нет)
|
||||
+ [Что такое гринлеты. Общее понятие. Примеры реализаций](questions.md/#Что-такое-гринлеты-Общее-понятие-Примеры-реализаций)
|
||||
* [Какие варианты реализации шаблона Singleton на питоне](questions.md/#Какие-варианты-реализации-шаблона-Singleton-на-питоне)
|
||||
* [Какие вы знаете инструменты для проверки кодстайл](questions.md/#Какие-вы-знаете-инструменты-для-проверки-кодстайл)
|
||||
@@ -199,7 +202,7 @@
|
||||
* [Опишите алгоритм работы CSRF middleware](questions.md/#Опишите-алгоритм-работы-CSRF-middleware)
|
||||
* [Что такое сигналы? Зачем нужны? Назовите основные](questions.md/#Что-такое-сигналы-Зачем-нужны-Назовите-основные)
|
||||
* [Как реализуется связь m2m на уровне базы данных](questions.md/#Как-реализуется-связь-m2m-на-уровне-базы-данных)
|
||||
* [Чем лучше отправлять форму — GET или POST](questions.md/#Чем-лучше-отправлять-форму-—-GET-или-POST)
|
||||
* [Чем лучше отправлять форму — GET или POST](questions.md/#Чем-лучше-отправлять-форму--GET-или-POST)
|
||||
* [Как работает Serializer в Django REST Framework](questions.md/#Как-работает-Serializer-в-Django-REST-Framework)
|
||||
* [Что такое Meta в классах Django и для чего нужен](questions.md/#Что-такое-Meta-в-классах-Django-и-для-чего-нужен)
|
||||
* [За что отвечает Meta в сериализаторе](questions.md/#За-что-отвечает-Meta-в-сериализаторе)
|
||||
@@ -232,7 +235,7 @@
|
||||
+ [Наследование](questions.md/#Наследование)
|
||||
+ [Полиморфизм](questions.md/#Полиморфизм)
|
||||
+ [Абстракция](questions.md/#Абстракция)
|
||||
* [Какие принципы программирования вы знаете](questions.md/#Какиe-принципы-программирования-вы-знаете)
|
||||
* [Какие принципы программирования вы знаете](questions.md/#Какие-принципы-программирования-вы-знаете)
|
||||
+ [KISS](questions.md/#KISS)
|
||||
+ [DRY](questions.md/#DRY)
|
||||
+ [YAGNI](questions.md/#YAGNI)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
- yakimka: https://github.com/yakimka
|
||||
- pavlenk0: https://github.com/pavlenk0
|
||||
118
generate_toc.py
Normal file
118
generate_toc.py
Normal file
@@ -0,0 +1,118 @@
|
||||
import dataclasses
|
||||
import re
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclasses.dataclass()
|
||||
class Header:
|
||||
name: str
|
||||
level: int
|
||||
|
||||
@property
|
||||
def slug(self):
|
||||
text = self.name.replace(' ', '-')
|
||||
# single chars that are removed
|
||||
text = re.sub(r'[`~!@#$%^&*()+=<>?,./:;"\'|{}\[\]\\–—]', '', text)
|
||||
# CJK punctuations that are removed
|
||||
text = re.sub(r'[ 。?!,、;:“”【】()〔〕[]﹃﹄“”‘’﹁﹂—…-~《》〈〉「」]', '', text)
|
||||
return text
|
||||
|
||||
|
||||
class TOCMaker:
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
max_depth=6,
|
||||
link_prefix='',
|
||||
indentation_size=2,
|
||||
list_bullets=('-', '*', '+', '-'),
|
||||
header_class=Header,
|
||||
):
|
||||
self.max_depth = max_depth
|
||||
self.link_prefix = link_prefix
|
||||
self.indentation_size = indentation_size
|
||||
self.list_bullets = list_bullets
|
||||
self.header_class = header_class
|
||||
|
||||
def make(self, text):
|
||||
headers = self._collect_headers(text)
|
||||
return self._make_toc(headers)
|
||||
|
||||
def make_from_file(self, fp):
|
||||
return self.make(fp.read())
|
||||
|
||||
def _collect_headers(self, text):
|
||||
headers = []
|
||||
|
||||
code_blocks = 0
|
||||
for line in text.splitlines():
|
||||
line = line.strip()
|
||||
code_blocks += line.count('```') % 2
|
||||
if code_blocks % 2 == 0 and line.startswith('#'):
|
||||
header = self._parse_header_from_line(line)
|
||||
if header.level <= self.max_depth:
|
||||
headers.append(self._parse_header_from_line(line))
|
||||
|
||||
return headers
|
||||
|
||||
def _make_toc(self, headers: List[Header]):
|
||||
toc = []
|
||||
for header in headers:
|
||||
indentation = ' ' * ((header.level - 1) * self.indentation_size)
|
||||
bullet = self._get_bullet(header.level)
|
||||
toc.append(f'{indentation}{bullet} [{header.name}]({self.link_prefix}#{header.slug})')
|
||||
return '\n'.join(toc)
|
||||
|
||||
def _get_bullet(self, level):
|
||||
if level > len(self.list_bullets):
|
||||
return self.list_bullets[-1]
|
||||
return self.list_bullets[level - 1]
|
||||
|
||||
def _parse_header_from_line(self, line):
|
||||
level = 0
|
||||
name = ''
|
||||
for char in line:
|
||||
if char == '#':
|
||||
level += 1
|
||||
else:
|
||||
name = line[level + 1:].strip()
|
||||
break
|
||||
|
||||
return self.header_class(
|
||||
name=name,
|
||||
level=level
|
||||
)
|
||||
|
||||
|
||||
def paste_after(delimiter, content, text):
|
||||
result = []
|
||||
for line in text.splitlines():
|
||||
if line.strip() != delimiter:
|
||||
result.append(line)
|
||||
else:
|
||||
result.append(f'{delimiter}\n')
|
||||
result.append(f'{content}\n')
|
||||
return '\n'.join(result)
|
||||
|
||||
raise ValueError(f"Can't find delimiter '{delimiter}'")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
with open('questions.md') as fp:
|
||||
maker = TOCMaker(link_prefix='questions.md/')
|
||||
toc = maker.make_from_file(fp)
|
||||
|
||||
with open('README.md', 'r') as fp:
|
||||
original = fp.read()
|
||||
changed = paste_after('<!-- toc -->', toc, original)
|
||||
|
||||
if '--check' in sys.argv:
|
||||
if original != changed:
|
||||
print('Error')
|
||||
sys.exit(1)
|
||||
else:
|
||||
with open('README.md', 'w') as fp:
|
||||
fp.write(changed)
|
||||
|
||||
print('Done')
|
||||
@@ -4,9 +4,9 @@ title:
|
||||
text: Вопросы для подготовки к Python Developer интервью
|
||||
- type: edition
|
||||
text: build 1
|
||||
creator:
|
||||
- role: author
|
||||
text: yakimka
|
||||
author:
|
||||
- yakimka <https://github.com/yakimka>
|
||||
- pavlenk0 <https://github.com/pavlenk0>
|
||||
toc-title: Содержание
|
||||
language: ru-RU
|
||||
stylesheet: book_res/style.css
|
||||
|
||||
Reference in New Issue
Block a user