Code with Cyrmax
101 subscribers
18 links
Добро пожаловать на второй мой канал, на котором мы обсуждаем исключительно всё, связанное с программированием, сисадминством, профессиональными тулзами, операционками и прошивками. Ноу токсик, ноу политикс энд релиджен!
Download Telegram
#Python #Linter #flake8

Я программирую на Python достаточно давно, и если раньше это были какие-то бессмысленные программы из тридцати строчек, полезные лишь мне, то сейчас я учусь писать и Telegram-ботов, и бэкэнды, пусть и простенькие, и даже попытался влезть в разработку дополнений для NVDA со своим двустрочником для Дискорда.
И я ещё помню то время, когда мне было 16 18, и я писал код в блокноте, не зная ни про IDE с редакторами кода, ни уж тем более про форматирование и линтинг.‍

А вот в 2021 году, заново познакомившись с разработчиками TTMediaBot, я узнал много нового об уже казалось привычном языке программирования Python.
Я узнал про pep8, про автоматические форматтеры, про правильную сортировку импортов в начале файла, про статическую проверку типов наконец.
Тогда мне посоветовали Black в качестве инструмента форматирования кода и Flake8 как хороший пример линтера.
Я ими так и пользовался до недавних времён, внося лишь незначительные изменения в конфигурационные файлы, чтобы изменить желаемую длину строки, отключить некоторые предупреждения или другим образом форматировать выходные данные в случае найденных ошибок.
Однако, буквально пару недель назад я решил попробовать все все все плагины для flake8 (их список я нашёл тут https://github.com/DmytroLitvinov/awesome-flake8-extensions).‍

Ой чего там только не было!
Я нашёл и сборники самых частых ошибок, и анализаторы асинхронного кода, и даже спеллчекер там был.
И конечно же я радостно всё это поставил с бодрым настроем хотябы один проект написать вот так, обложившись со всех сторон строжайшими проверками и ограничениями.‍

Но суровая реальность как всегда внесла свои коррективы.
Во-первых, в этом огромном списке оказалась некоторая доля нещадно устаревших плагинов, которые неслабо сломали мне виртуальное окружение.
Их пришлось выкинуть сразу, а венв пересоздавать заново.
Во-вторых, половина плагинов так или иначе дублировала друг друга, выкидывая по три четыре ошибки на одну строку, немного с разным форматом вывода, но с одной и той же сутью.
В-третьих, некоторые плагины были просто лишены здравого смысла!
Например, спеллчекер не понимал, где название стороннего пакета, а где мой код, ругаясь на странное слово wx или совсем непонятное from scipy.signal.windows import hamming.
А плагин, проверяющий, что все импортируемые мной пакеты прописаны в requirements.txt, пытался найти там мои же локальные модули, лежащие в папке проекта.
Ну и самое бредовое: плагин, должный проверять отсутствие зацикленных импортов и правильное подключение пакетов для аннотации типов, просто сломал мне мозг.
Был такой код:

from typing import Any, Awaitable, Callable


На этот код он начал ругаться, чтобы я спрятал его за условием if TYPE_CHECKING.
Код превратился в нечто похожее на

from typing import TYPE_CHECKING
if TYPE_CHECKING: from typing import Any, Awaitable, Callable


На что доблестный чекер сообщил, что import TYPE_CHECKING тоже нужно спрятать под условие if TYPE_CHECKING.
В общем, здравого смысла ноль, зато дотошно и внимательно.

Но были и полезные дублирования ошибок.
Например, если стандартная ошибка flake8 E722 просто гласит "Do not use bare except", то похожая ошибка от flake8-bugbear уже пытается анализировать контекст и предполагать, какие именно исключения нужно ловить. В итоге от этого плагина вывод получается информативнее: "Do not use bare except. Catch exact exceptions instead to avoid catching memory errors or keyboard interrupts. Here for example you can use except NetworkError instead of bare except".
Это конечно не дословно, но выглядит примерно так.

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

p.s Единственный минус такого количества плагинов - это то, что проект из десяти файлов проверяется около пятнадцати секунд, что значительно дольше, чем с обычным Flake8 без плагинов.
Но вот VS Code почему-то не лагает, видимо как-то оптимизирует эти проверки.
#NVDA #Python

Я это сделал!
Может быть для более опытных в создании аддонов для NVDA разработчиков это не станет откровением, но я всё же смог настроить себе полноценное окружение, с автокомплитом, линтингом и прочими приятными штуками.
Теперь, когда я открываю workspace в VS Code, я получаю автоматическую документацию по всем модулям NVDA, автодополнение по методам и свойствам и даже поддержку статического анализатора типов (в тех местах конечно, где в самих исходниках NVDA размечены типы и написана документация).
И даже общий с исходниками NVDA стиль кода получается соблюдать с помощью честно украденной конфигурации для flake8.
Осталось только настроить Black для форматирования в том же стиле, и вообще будет сказка.

Так действительно программировать проще, и теперь, возможно, я смогу полноценно присоединиться к огромному сообществу аддоноделов всех мастей.
#Алгоритмы #Python #Занятно

Я уже публиковал это на своём основном канале, но не выложить и сюда не могу.

Безопасность и любопытство.

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

Когда я узнал об этом алгоритме, я сначала хотел сделать простого бота в Telegram или страничку в интернете, которая будет просить номер карты и однозначно отвечать, настоящие ли данные вы ввели.
Но потом я понял, что дураков, готовых предоставить реальный номер карты какому-то боту или сайту найдётся мало, а кто-то ещё на меня и в полицию пожалуется за попытку украсть данные, поэтому наглядную демонстрацию работы алгоритма я, к сожалению, смогу показать только тем, кто мне реально доверяет (конечно же не публично и конечно же с обещанием сразу же забыть все услышанные последовательности цифр) :D

После этого я решил, что опубликую этот пост, призову людей в комментарии с целью высказаться, знаете ли вы о чём идёт речь, есть ли у вас идеи.
А в конце поста оставлю ссылку на код.
Прикол в том, что у ссылки должен был быть таймер, чтобы она не открывалась раньше какого-то заданного времени.
Однако, сервисов с таким функционалом я не нашёл, что очень грустно.
И поэтому, в конце поста будет обычная унылая и скучная ссылка на pastebin с фрагментом кода на Python.

Но, если вы что-то знаете об алгоритме Луна, или у вас есть предположения о том, как можно даже без компьютера проверить валидность номера банковской карты, лучше сначала напишите в комментариях, а потом уже открывайте код :)

Обещанная ссылка:
https://pastebin.com/PffUJp0U‍

Пароль для ссылки:
1t2ry8pALJ‍

p.s Вот такой я плохой, сделал пароль зачем-то :)
На самом деле просто хотелось проверить как это работает, ибо никогда не пользовался защитой ссылок паролем на pastebin.
#Программирование #Python

А давайте напишем на Питоне бесконечный калькулятор в одну строчку кода?
Именно этим я под вечер и занялся.
После трёх минут гугления, двух минут написания кода и ещё минуты на исправление автоформатирования получилось это:

[print(eval(s)) for s in map(lambda x: input("Enter expression"), __import__("itertools").count())]

Оно действительно в одну строчку и оно действительно работает.

Вот примерно так любят показывать свой супер-скилл некоторые программисты на CodeWars.
Code with Cyrmax
#Программирование #Python А давайте напишем на Питоне бесконечный калькулятор в одну строчку кода? Именно этим я под вечер и занялся. После трёх минут гугления, двух минут написания кода и ещё минуты на исправление автоформатирования получилось это: [print(eval(s))…
#Программирование #Python

По просьбе читателя кратко разбираем однострочный калькулятор из предыдущего поста.
Напомню код:

[print(eval(s)) for s in map(lambda x: input("Enter expression"), __import__("itertools").count())]

Как это получилось?

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

print(eval(input("Enter your expression")))

Читая изнутри наружу, видим ввод данных, выполнение выражения функцией eval и вывод результата на консоль.

Но нам нужно, чтобы эта последовательность выполнялась бесконечно и всё ещё занимала лишь одну строчку, одну инструкцию.
Можно было бы сделать while True: print(eval(input("Enter expression"))), и у нас тоже была бы формально одна строка, но инструкций было бы уже две, а это неспортивное читерство.
Да и код должен выглядеть страшнее, чем просто куча скобочек.
Давайте подумаем, что кроме циклов может повторять некую операцию множество раз?
Правильно, это либо функции преобразования последовательностей, либо list comprehensions, те, что в квадратных скобках.
Вот их мы и используем.
У list comprehension в начале пишется выражение, результат которого будет образовывать новый элемент конструироемого списка. Обычно это просто название переменной либо какое-то преобразование над переменной.
Но никто не запрещает нам вписать любой валидный код.
Собственно мы и пишем print(eval(s)). Откуда мы взяли s? Из правой части, в которой у списочных выражений располагается цикл для перебора некой последовательности.
А вот где нам взять эту самую последовательность, причём бесконечную?
В пакете itertools есть бесконечный итератор count, представляющий собой счётчик, по умолчанию возвращающий целые числа начиная с нуля.
Но импортировать itertools привычным способом мы не можем, так как это будет уже вторая строчка, а у нас вполне чёткое условие - уложиться в одну инструкцию.
Вспоминаем про встроенную функцию языка __import__, принимающую на вход строку с именем пакета и возвращающую объект этого пакета, только без имени.
Отсюда и получаем __import__("itertools").count(). Просто импортируем itertools, через точку создаём объект count и тут же его используем в качестве параметра, нигде не сохраняя.
С лямбдой, думаю, всё понятно, она просто принимает строку от пользователя.
Ну а map просто повторяет эту лямбду для каждого элемента нашей бесконечной последовательности, не более того.

А вообще, на самом деле, всё можно было сделать намного проще.
Только начав писать этот пост, я сразу сообразил, что можно было не танцевать с мапом и лямбдой; ведь как я уже сказал в начале, list comprehension в левой части может содержать любой, абсолютно любой код.
А поэтому всю конструкцию можно значительно упростить и привести к вот такому виду:

[print(eval(input("Enter Expression"))) for _ in __import__("itertools").count()]

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

Наверное можно ещё проще, но на скорую руку в голову ничего не приходит.
👍1
#Программирование #Эзотерика #Однострочники #Python

Один хороший человек на днях скинул мне страшнющий однострочник на Python, а затем сотворил вот это руководство.
Пользуйтесь и наслаждайтесь... Если сможете :)
@denizsincar29, спасибо тебе!

Руководство по созданию чудовищных, но эффектных однострочников:

Цель: Уместить максимальное количество логики и операций в одну строку кода, жертвуя читаемостью, поддерживаемостью и безопасностью. Наша цель - создать код, который никто не сможет понять, кроме самого гения-автора (да и то не факт).

Основные принципы:

• Забудьте про обработку исключений: Ошибки - это весело! Пусть программа взрывается. Обработать исключения в однострочнике невозможно, поэтому мы не будем даже пытаться.
• Комбинируйте всё воедино (максимально): Вложенные тернарные операторы, цепочки методов, скобки внутри скобок - чем больше операций в одном выражении, тем лучше. (a if cond1 else (b if cond2 else c)) - ваш лучший друг. a or b and c - тоже полезно для создания неочевидной логики.
• Лист-компрехеншены - наше многофункциональное оружие: Превратите любой цикл и фильтрацию данных в однострочный ад. Используйте вложенные лист-компрехеншены для максимальной сложности. Да и цикл в одну строку вы не напишете.
• Мгновенная индексация - для краткости и скорости: Создайте список/словарь на лету и сразу же получите к нему доступ по индексу/ключу. [...][i] и {...}[key] позволяют избежать временных переменных и сделать код более лаконичным. Убедитесь, что i и key вычисляются в других сложных выражениях, чтобы увеличить уровень абстракции.
• Импортируйте не как все (для obfuscation): __import__("module").submodule.function() - это не только красиво, но и затрудняет анализ зависимостей.
• Циклы через itertools (для бесконечной мощи): Забудьте про обычные for. __import__("itertools").count() и map() с лямбдами позволяют создавать бесконечные циклы, которые могут привести к зависанию программы, если их не остановить.
• Больше тернарных операторов (для нелинейной логики): Выведите тернарные операторы на новый уровень, вложив их друг в друга несколько раз. Используйте их даже там, где они не нужны, чтобы добавить немного загадочности.
• Главное - уместить как можно больше: Каждая строка должна быть наполнена операциями до предела. Используйте все доступные приемы, чтобы уменьшить количество символов и увеличить плотность логики.

Пример (стремящийся к абсолютной нечитаемости):

monthdays = lambda year, month: [31, (29 if (((year % 4) == 0) and ((year % 100) != 0) or ((year % 400) == 0)) else 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][(["январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"].index(month.strip().lower()))] # Возвращает количество дней в месяце для заданного года (или взрывается с ошибкой). Не пытайтесь понять, как это работает.

Полезные применения (и предостережения):

• Конкурсы на самый нечитаемый код (где побеждает тот, кто умудрится сделать больше всего в одной строке).
• Демонстрация *мнимого* мастерства владения языком (если кто-то действительно впечатлится, вам повезло).
• Запутывание врагов (только если вы уверены, что они не смогут использовать ваш код против вас).

Важное предупреждение:
Этот код предназначен только для развлечений и экспериментов! Вы можете конечно использовать такой код на работе, *если ваша цель - отомстить вашему работодателю перед увольнением*.
😭2❤‍🔥1🔥1