mentortools/libs/: run-markdown-1.2.68107 metadata and description
Extract and run code blocks from .md files
| author | Mike Orlov |
| author_email | m.orlov@technokert.ru |
| classifiers |
|
| description_content_type | text/markdown |
| license | Unpublished |
| requires_dist |
|
| requires_python | >=3.11,<4.0 |
| File | Tox results | History |
|---|---|---|
run_markdown-1.2.68107-py3-none-any.whl
|
|
|
run_markdown-1.2.68107.tar.gz
|
|
RunMarkdown
Extract and run code blocks from .md files
Пример проверки кода на python
Код, маркированный, как python, будет запущен с помощью python
print(2+3)
Следующий блок текста за исполняемым блоком будет использоваться для проверки результата
5
Пример создания и последующего импорта файла на python
Если текст перед блоком кода заканчивается жирной строкой, начинающийся с file:// и заканчивающийся на :,
то код из блока будет предварительно помешён в файл(можно указывать три слеша подряд, чтобы не создавалась ссылка)
Например, создадим file:///summarize.py:
def summarize(a: int, b: int) -> int:
return a + b
Если после блока кода нет текстового блока, то код запускается, но проверка не выполняется
Импортируем созданный файл
from summarize import summarize
print(summarize(3, 4))
Проверим, что вывелось
7
Созданные файлы в текущей версии живут до окончания всего запуска, но это может измениться в дальнейшем
Пример проверки кода, не завершающегося за 1 сек
run_markdown имеет таймаут на выполнение каждого блока кода.
По дефолту это 1 секунда. Этот параметр принимается во втором аргументе запуска.
Помимо python можно также запускать код на bash/sh.
Следующий код будет 6 секунд выводить числа подряд.
for i in {1..20}; do echo $i; sleep 0.3; done
По поскольку мы прождём только 1 секунду, то увидим первые 4 числа:
1
2
3
4
Пример проверки кода, c шаблонизированным результатом
Для текстовых результатов есть механизм, позволяющий проверять наличие только определённых строк и/или подстрок в выводе блока
Шаблонизированные строки
Для шаблонизации строки есть символ три точки подряд ....
Он интерпретируется, как любое количество любых символов, кроме переноса строки.
Пример 1
Следующий код выведет текущий год
import datetime
print(datetime.datetime.now().year)
Допустим, мы хотим проверить первые два символа года, тогда нам подойдёт следующая запись:
20...
Она обозначает, что мы ожидаем одну строку, начинающуюся с 20 и любое количество любых символов дальше.
Пример 2
Похожий пример на bash
date
мы получим примерно такую строку: Wed Feb 12 01:26:41 PM MSK 2025
Допустим, мы так же хотим проверить, что текущий год начинается с 20
Тогда напишем следующую проверку:
... 20...
Она обозначает, что мы ожидаем одну строку, начинающуюся с любого количества любых символов, потом 20
и любое количество любых символов дальше.
Пример 3
Рассмотрим пример с несколькими строками
1/0
Этот код выбросит исключение следующего вида:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
Допустим, нас не интересует стек, а только само исключение. Тогда мы можем написать так:
...
...
ZeroDivisionError: division by zero
Получится, что мы игнорируем дву строки, а в третьей ожидаем полного соответствия
Пропуск строк
В прошлом примере мы игнорировали ровно две строки, но бывает так,
что большую часть строк мы хотим проигнорировать, а проверить наличие меньшей.
Или бывает, что мы не знаем точное количество строк, которое хоти проигнорировать.
Тогда можно использовать три звёздочки подряд: ***
Эта последовательность символов должна быть написана на отдельной строке и тогда она обозначает,
что любое количество любых строк может быть проигнорировано.
Рассмотрим примеры
Пример 1
Следующий код выведет 0-5 раз строку hay(сено), один раз строку needle(иголка) и ещё 0-5 раз hay
import datetime
[print("hay") for _ in range(datetime.datetime.now().second // 10)]
print('needle')
[print("hay") for _ in range(datetime.datetime.now().minute // 10)]
Допустим, мы хотим проверить, что вывелась строка needle, тогда нам нужно написать следующее:
***
needle
***
Получается, что мы игнорируем любое количество строк до строки needle и любое количество после
Внимание
Шаблон с большим количеством тройных звёздочек, разделённых строками, при большом выводе кодового блока, который НЕ соответствует шаблону, может упереться в производительность (зависнуть), так как будет перебирать очень большое количество вариантов сопоставления большого вывода, Например, если кодовый блок вывел
0
1
2
3
4
5
А шаблон выглядит, как
***
5
***
3
***
1
***
То вычислительная сложность грубо оценивается, как количество строк вывода В СТЕПЕНИ количества тройных звёздочек. Таким образом при выводе не 5ти чисел, а 500ти вычислительная сложность вырастет 100000000 раз!
Пример проверки кода, возвращающего json
В json порядок атрибутов объектов не гарантирован, что может стать проблемой при текстовом сравнении.
Кроме того минифицированный json (без переносов строк и пробелов) эквивалентен своей полной форме.
import json
print(json.dumps({"a": 1, "b": 2})) # напечатает строку '{"a": 1, "b": 2}'
Опишем ожидаемый результат в развёрнутом виде: Т.к. мы указали тип json, а не text, то проверка успешно прошла
{
"b": 2,
"a": 1
}
Пример проверки кода, возвращающего из python stderr
Кроме стандартного потока вывода(stdout) есть ещё и поток ошибок(stderr), они объединяются в единый вывод. (вызов выполняется через утилиту script)
import sys
print("something")
print('other', file=sys.stderr)
print('''third\nforth''', file=sys.stderr)
Опишем ожидаемый результат в развёрнутом виде:
something
other
third
forth
Примечание
К сожалению, из-за буфферизации может меняться порядок вывода строк из stdout и stderr друг относительно друга. Поэтому такой подход работает далеко не всегда
Пример многострочника c кавычками на bash
Расположение целевого файла
Для некоторых тестов может быть полезно обратиться к файлам рядом с целевым md файлом.
Например, выведем содержимое текущего файла и проверим, что в нём есть эта строка:
cat $ORIGIN_DIR/README.md
Проверяем:
***
...проверим, что в нём есть эта строка
***