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
|
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
|
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, хочу читать в электронной книге
|
### Не хочу читать в Markdown, хочу читать в электронной книге
|
||||||
|
|
||||||
@@ -60,7 +63,7 @@
|
|||||||
+ [Что возвращает метод items](questions.md/#Что-возвращает-метод-items)
|
+ [Что возвращает метод items](questions.md/#Что-возвращает-метод-items)
|
||||||
+ [Как отсортировать список словарей по определенному полю](questions.md/#Как-отсортировать-список-словарей-по-определенному-полю)
|
+ [Как отсортировать список словарей по определенному полю](questions.md/#Как-отсортировать-список-словарей-по-определенному-полю)
|
||||||
+ [Что может являться ключом словаря. Что не может. Почему](questions.md/#Что-может-являться-ключом-словаря-Что-не-может-Почему)
|
+ [Что может являться ключом словаря. Что не может. Почему](questions.md/#Что-может-являться-ключом-словаря-Что-не-может-Почему)
|
||||||
+ [Есть два списка – ключи и значения. Как составить из них словарь](questions.md/#Есть-два-списка-–-ключи-и-значения-Как-составить-из-них-словарь)
|
+ [Есть два списка – ключи и значения. Как составить из них словарь](questions.md/#Есть-два-списка--ключи-и-значения-Как-составить-из-них-словарь)
|
||||||
+ [Как работает хэш-таблица](questions.md/#Как-работает-хэш-таблица)
|
+ [Как работает хэш-таблица](questions.md/#Как-работает-хэш-таблица)
|
||||||
+ [Что такое коллизия](questions.md/#Что-такое-коллизия)
|
+ [Что такое коллизия](questions.md/#Что-такое-коллизия)
|
||||||
+ [Где будет быстрее поиск, а где перебор и почему: dict, list, set, tuple](questions.md/#Где-будет-быстрее-поиск-а-где-перебор-и-почему-dict-list-set-tuple)
|
+ [Где будет быстрее поиск, а где перебор и почему: dict, list, set, tuple](questions.md/#Где-будет-быстрее-поиск-а-где-перебор-и-почему-dict-list-set-tuple)
|
||||||
@@ -183,7 +186,7 @@
|
|||||||
+ [В чем отличие тредов от мультипроцессинга](questions.md/#В-чем-отличие-тредов-от-мультипроцессинга)
|
+ [В чем отличие тредов от мультипроцессинга](questions.md/#В-чем-отличие-тредов-от-мультипроцессинга)
|
||||||
+ [Какие задачи хорошо параллелятся, какие плохо](questions.md/#Какие-задачи-хорошо-параллелятся-какие-плохо)
|
+ [Какие задачи хорошо параллелятся, какие плохо](questions.md/#Какие-задачи-хорошо-параллелятся-какие-плохо)
|
||||||
+ [Нужно посчитать 100 уравнений. Делать это в тредах или нет](questions.md/#Нужно-посчитать-100-уравнений-Делать-это-в-тредах-или-нет)
|
+ [Нужно посчитать 100 уравнений. Делать это в тредах или нет](questions.md/#Нужно-посчитать-100-уравнений-Делать-это-в-тредах-или-нет)
|
||||||
+ [Треды в Питоне — это нативные треды или нет](questions.md/#Треды-в-Питоне-—это-нативные-треды-или-нет)
|
+ [Треды в Питоне — это нативные треды или нет](questions.md/#Треды-в-Питоне--это-нативные-треды-или-нет)
|
||||||
+ [Что такое гринлеты. Общее понятие. Примеры реализаций](questions.md/#Что-такое-гринлеты-Общее-понятие-Примеры-реализаций)
|
+ [Что такое гринлеты. Общее понятие. Примеры реализаций](questions.md/#Что-такое-гринлеты-Общее-понятие-Примеры-реализаций)
|
||||||
* [Какие варианты реализации шаблона Singleton на питоне](questions.md/#Какие-варианты-реализации-шаблона-Singleton-на-питоне)
|
* [Какие варианты реализации шаблона Singleton на питоне](questions.md/#Какие-варианты-реализации-шаблона-Singleton-на-питоне)
|
||||||
* [Какие вы знаете инструменты для проверки кодстайл](questions.md/#Какие-вы-знаете-инструменты-для-проверки-кодстайл)
|
* [Какие вы знаете инструменты для проверки кодстайл](questions.md/#Какие-вы-знаете-инструменты-для-проверки-кодстайл)
|
||||||
@@ -199,7 +202,7 @@
|
|||||||
* [Опишите алгоритм работы CSRF middleware](questions.md/#Опишите-алгоритм-работы-CSRF-middleware)
|
* [Опишите алгоритм работы CSRF middleware](questions.md/#Опишите-алгоритм-работы-CSRF-middleware)
|
||||||
* [Что такое сигналы? Зачем нужны? Назовите основные](questions.md/#Что-такое-сигналы-Зачем-нужны-Назовите-основные)
|
* [Что такое сигналы? Зачем нужны? Назовите основные](questions.md/#Что-такое-сигналы-Зачем-нужны-Назовите-основные)
|
||||||
* [Как реализуется связь m2m на уровне базы данных](questions.md/#Как-реализуется-связь-m2m-на-уровне-базы-данных)
|
* [Как реализуется связь 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)
|
* [Как работает Serializer в Django REST Framework](questions.md/#Как-работает-Serializer-в-Django-REST-Framework)
|
||||||
* [Что такое Meta в классах Django и для чего нужен](questions.md/#Что-такое-Meta-в-классах-Django-и-для-чего-нужен)
|
* [Что такое Meta в классах Django и для чего нужен](questions.md/#Что-такое-Meta-в-классах-Django-и-для-чего-нужен)
|
||||||
* [За что отвечает Meta в сериализаторе](questions.md/#За-что-отвечает-Meta-в-сериализаторе)
|
* [За что отвечает Meta в сериализаторе](questions.md/#За-что-отвечает-Meta-в-сериализаторе)
|
||||||
@@ -232,7 +235,7 @@
|
|||||||
+ [Наследование](questions.md/#Наследование)
|
+ [Наследование](questions.md/#Наследование)
|
||||||
+ [Полиморфизм](questions.md/#Полиморфизм)
|
+ [Полиморфизм](questions.md/#Полиморфизм)
|
||||||
+ [Абстракция](questions.md/#Абстракция)
|
+ [Абстракция](questions.md/#Абстракция)
|
||||||
* [Какие принципы программирования вы знаете](questions.md/#Какиe-принципы-программирования-вы-знаете)
|
* [Какие принципы программирования вы знаете](questions.md/#Какие-принципы-программирования-вы-знаете)
|
||||||
+ [KISS](questions.md/#KISS)
|
+ [KISS](questions.md/#KISS)
|
||||||
+ [DRY](questions.md/#DRY)
|
+ [DRY](questions.md/#DRY)
|
||||||
+ [YAGNI](questions.md/#YAGNI)
|
+ [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 интервью
|
text: Вопросы для подготовки к Python Developer интервью
|
||||||
- type: edition
|
- type: edition
|
||||||
text: build 1
|
text: build 1
|
||||||
creator:
|
author:
|
||||||
- role: author
|
- yakimka <https://github.com/yakimka>
|
||||||
text: yakimka
|
- pavlenk0 <https://github.com/pavlenk0>
|
||||||
toc-title: Содержание
|
toc-title: Содержание
|
||||||
language: ru-RU
|
language: ru-RU
|
||||||
stylesheet: book_res/style.css
|
stylesheet: book_res/style.css
|
||||||
|
|||||||
Reference in New Issue
Block a user