Как стать автором
Обновить
13
0
Николай @Niccolum

Python backend developer

Отправить сообщение

Нене, выдаст оба, при прочих равных. Просто % будет выше у первой строки.
Т.е., согласно доке, будет 0 у первой строки, и 1 у второй.

P.S. Я не про soundex, а про levenshtein.

Работает по алгоритму левенштейна, проблем и неудобных юзкейсов не испытывал.

Есть одна особенность. У него левенштейн по подстроке, т.е.

Если в базе
"ООО Рога и Копыта"
И
"ООО Рыг"

И мы ищем по "ООО Рог", то найдёт первую строку, и покажет 100% совпадение.

Т.е. оно магически находит наиболее похожую подстроку, и показывает левенштейн по ней.

Чем не подошёл модуль fuzzystrmatch для полнотекстового поиска? Он лишён тех минусов, о которых вы упоминали в статье

1 В этом и суть. Иначе такие тесты кроме имени схемы ничего не валидируют.

4 Строить тесты таким образом, чтобы они документировали сами себя? Прям как код? Естественно, такое возможно не всегда, но очень часто этого достаточно.

5 Есть строгая/нестрогая типизация. Также есть статическая/динамическая. То, что вы, говоря о строгой типизации, имеете ввиду строгую статическую, желательно упоминать явно.

2

Проверки должны быть полными, то есть мы должны проверить статус код ответа, данные в теле ответа, провалидировать JSON схему;

Если вы хотите валидировать жсон схему - используйте отдельную схему от той, что вы используете в коде явно. Иначе вы не отловите кейсы изменения схемы, которые, как я понимаю, должны падать. Иначе тест сводится к "в этом эндпоинте используется схема с этим именем"

Автотесты должны быть документированными и поддерживаемыми. Чтобы автотесты мог читать и писать не только QA Automation, но и разработчик;

Документирование автотестов выглядит как что-то ненужное. Максимум, что можно сказать о документированности - из имени метода должно быть понятно что делает этот тест или к чему призван, из за чего написан.

Хотелось бы, чтобы JSON схема и тестовые данные генерировались автоматически на основе документации;

Посмотрите в сторону faker и подобных инструментов. Наверняка есть что то, что генерирует данные на основе пидантик схемы

Отчет должен быть читабельным, содержав в себе информацию о ссылках, заголовках, параметрах, с возможностью прикреплять какие-то логи.

Выглядит как что то совсем излишнее. Если это, конечно, не касается end2end тестов

3 Это всё ещё означает, что процессы плохо выстроены именно у вас

6 Вы сначала говорите, что в python нет строгой типизации и сразу же себя опровергаете. Не надо так :)

8 Если я правильно понял комментатора выше, имелось ввиду не настройки в фикстуру, а сделать функцию с кэшем получения настроек. Как в доке фастапи. Если мы говорим опять же про фастапи, то можно настройки подменять через Depends. Фикстуру, к слову, можно прикинуть во все тесты, явно её не передавая из за магии autouse=True.

10 Модель Authentication вполне может в валидацию того, что вы написали в клиенте. Мне кажется, комментатор выше именно это имел ввиду.

У вас счётчик некорректно статус выдаёт

Почитал то, что у вас получилось.

Несомненно, была проделана большая работа, на своей работе делали нечто подобное, использовав cookiecutter. От себя хочу посоветовать пару вещей:

  1. Один сеттингс файл это конечно ужас. Посмотрите в сторону django-split-settings, нам это помогло для разбития конфига на несколько файлов, для читаемости.

  2. Есть некоторые архаичные вещи, такие, как settings.ini, который, как я вижу, совсем не используется. Провести бы рефакторинг всего проекта на поиск таких артефактов.

  3. Взгляните на pre-commit. Позволит вам запускать все линтеры разом, в том числе для js кода, несмотря на то, что библиотека для питона.

  4. В приложении защиты линтеры по вашему желанию. Хотелось бы иметь более гибкий инструмент, чтобы он использовался и вне вашей организации. Пока он заточен именно под неё.

  5. Скорее совет. Вынесите BModel как плагин для джанги, отдельно от создания шаблона. Увеличит заинтересованность сторонних пользователей

  6. Ну и так, пока последнее, я так понял, что BModel это аналог компонента на vuejs, где всё находится в одном месте. Это конечно прикольно, но, имхо, слишком перегружено. Как вы правильно отметили - из за такой высокой абстракции сложно делать что то более настраиваемое. Я бы подумал в эту сторону, как развитие проекта. Например, в сторону DI, как работает сам drf.

Если вы про хранимый xss, то да, автор рассматривал этот вариант, да и я не вижу ничего плохого в том, чтобы, раз уж у меня кривые руки отловить это на входе - портить пользовательские данные (вырезать html теги) в базе.

Для защиты от sql инъекций достаточно экранирования, сомневаюсь, что кто то квери в базе хранит как строки.

По поводу "вырезать кавычки в json" и про почту - сюр какой-то))

Да нет, имелось ввиду именно то, что написано. Лично я не встречал, но вполне уверен, что может быть какой то код, где разрешается пользовательский ввод регулярок.
А проверка регулярками на сервере это вполне обычное удовольствие.

Вы просто перевели ридми проекта? Причем местами перевод выглядит, будто его сделал Гугл.

А каким образом наличие или отсутствие приватных методов влияет на объектно-ориентированность? То, что это может идти вкупе с остальным не говорит, что это является обязательным в ООП.

Возможно, я ошибся насчёт того, что контекст может переключиться во время выполнения атомарной операции. Мой косяк. Но видео тем не менее глянуть стоит, имхо

Можете посмотреть выступление Дэвида Бизли, где он объясняет старый и новый движок GIL. https://m.youtube.com/watch?v=ph374fJqFPE


В частности, теперь переключение будет происходить независимо от "атомарности операции", строго по внутреннему счётчику времени

Можете проверить самостоятельно, код абсолютно рабочий, необходимо только добавить пару импортов вначале, и, возможно, указать текстовые файлы корректно


import queue
import threading
import time
import os

Попробую поочерёдно разобрать, как это работает, в порядке, в котором оно запускается.


  1. follow. Идём в конец файла, пытаемся считать новую строку, если она есть. В противном случае спим
  2. multiplex. Создаём очередь, считываем в треде с помощью функции sendto_queue источник (функция follow) и в конце добавляем StopIteration, если мы завершили итерирование (в данном конкретном случае этого не произойдёт, т.к. вечный цикл)
  3. С помощью genfrom_queue считываем с очереди всё, что туда пришло. При StopIteration выходим из цикла
  4. С помощью gen_cat входим в контекст считывания очереди по мере её наполнения
  5. С помощью функции broadcast передаём один и тот же результат в разные экземпляры Consumer

Итак, где же тут магия, которая позволяет считывание из каждого из источников follow конкурентно? Всё дело в sleep у follow, что позволяет работать конкуррентно бесконечному циклу в треде и genfrom_queue, где у нас происходит из очереди, а не непосредственно из функций follow.


т.е. получается, что генератор работает не завершаясь, получая данные из очереди из тредов, хотя они работают в главном потоке


Чтобы подтвердить теорию, добавим src как один из аргументов в genfrom_queue


def genfrom_queue(thequeue, src):
    print(src.__name__)
    while True:
        item = thequeue.get()
        if item is StopIteration:
            break
        yield item
...
def multiplex(sources):
   ...
   consumers.append(genfrom_queue(in_q, src))
...
log1.__name__ = 'log1'
log2.__name__ = 'log2'
log3.__name__ = 'log3'

Как я выяснил в ходе дебага, можно убрать пару лишних шагов и всё продолжит работать. Возможно, это натолкнёт на какую то мысль


def multiplex(sources):
    in_q = queue.Queue()
    for src in sources:
        thr = threading.Thread(target=sendto_queue, args=(src, in_q))
        thr.start()
    yield from genfrom_queue(in_q)

Работает аналогично. В источнике Бизли, видимо, по какой то причине включили эти ненужные шаги

Условно говоря, с разных тредов всё валится в одну кучу (очередь) в фоновом режиме и gen_cat всё это добро разгребает в единый результирующий список

  1. В данном конкретном примере — только одна очередь и с несколькими работать не будет, верно. Ничего не мешает пример развить и работать с несколькими очередями, но это уже вне данной статьи.
  2. gen_cat(consumers) в примере входит внутрь каждого контекста genfrom_queue и забирает оттуда данные, распаковывая в единый список (похожее поведение с itertools.chain). gen_cat действительно работает в бесконечном цикле, однако мы предусмотрительно заставляем follow генераторы работать внутри треда, поэтому во время time.sleep будут отрабатывать (или также ожидать) другие треды.
    Так что никаких подводных камней тут нет. Треды решают второй вопрос, поставленный вами, т.к. используется одна очередь для всех тредов (всех follow файлов)

Честно говоря, впервые о ней услышал.
Увидел две. Одной около 8 лет, другая в процессе разработки, однако по обеим нет совершенно никакой документации, чтобы их можно было представить тут

На самом деле нет, однако на этот счёт есть занимательная ссылка, в которой раскрываются ошибки достаточно косвенно связанные, но всё таки связанные с тем, что переменные могут быть мутабельны (перезаписываться в ту же переменную). И, как можно увидеть, много проблем может быть косвенно связано именно с мутабельностью переменных, а это достаточно широкий пласт ошибок.
https://www.quora.com/Why-is-immutability-important-in-functional-programming


Большего, к сожалению, дать не смогу

Спасибо за уточнения, добавил описание ограничений под примерами в примечаниях

Не спорю, лишнее действие действительно происходит, в данном конкретном примере.
Возможно, получится сделать без этого лишнего принта, но пока не придумал как

1

Информация

В рейтинге
Не участвует
Откуда
Железнодорожный (Московск.), Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность