01 марта, 23:44
Python: декоратор с опциональной передачей аргументов

В процессе разработки нашего децентрализованного мультипротокольного мессенджера возникла задача создать декоратор для функции, способный вызываться как в виде @decorator так и @decorator(arg1, arg2). Мой товарищ MrBoriska создал сниппет, решающий эту проблему:

from functools import wraps
import inspect

def decorator_gen(*args, **kwargs):
    
    # Выясняем в каком режиме работаем
    as_decorator = False
    # Если передан один позиционный аргумент и он является callable обьектом
    if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
        # Необходимо дополнительно проверить, декорирован ли он нашим декоратором
        for line in inspect.getsourcelines(args[0])[0]:
            line = line.strip()
            if line.startswith("@decorator_gen"): # для параноиков можно еще проверять на отсутствие скобок
                as_decorator = True
                break
            if line.startswith("def") or line.startswith("async def"):
                break

    # >> причесываем args и kwargs тут <<

    def decorator(f):
        print("i am decorator")

        @wraps(f)
        def wrapper(*af, **kwf):
            # af и kwf - аргументы декорируемой функции f
            # args и kwargs - дополнительные параметры декоратора
            print("i am wrapper", (af,kwf))
            if as_decorator:
                print("no \"()\", no special args")
            f(*af, **kwf)
        return wrapper

    if as_decorator:
        # Если первый позиционный аргумент - функция, то работаем как декоратор
        return decorator(args[0])
    else:
        # Иначе, конфигурируем декоратор, и возвращаем его обьект-функцию
        print("i am generate decorator with arguments:", (args, kwargs))
        return decorator


@decorator_gen() # equal to @decorator_gen
def func(*args,**kwargs):
    print("i am func",(args,kwargs))

func(1,2)

Такой дескриптор будет железобетонно определять, какие параметры переданы и соответственно отрабатывать, однако если не предполагается, что первым (и единственным) аргументом в дескриптор может может передана callable функция, то можно упростить проверки и не подключать библиотеку inspect:

from functools import wraps

def decorator_gen(*args, **kwargs):
    
    # Выясняем в каком режиме работаем
   as_decorator = len(args) == 1 and len(kwargs) == 0 and callable(args[0])

    # >> причесываем args и kwargs тут <<

    def decorator(f):
        print("i am decorator")

        @wraps(f)
        def wrapper(*af, **kwf):
            # af и kwf - аргументы декорируемой функции f
            # args и kwargs - дополнительные параметры декоратора
            print("i am wrapper", (af,kwf))
            if as_decorator:
                print("no \"()\", no special args")
            f(*af, **kwf)
        return wrapper

    if as_decorator:
        # Если первый позиционный аргумент - функция, то работаем как декоратор
        return decorator(args[0])
    else:
        # Иначе, конфигурируем декоратор, и возвращаем его обьект-функцию
        print("i am generate decorator with arguments:", (args, kwargs))
        return decorator


@decorator_gen() # equal to @decorator_gen
def func(*args,**kwargs):
    print("i am func",(args,kwargs))

func(1,2)

А для того, чтобы подробнее узнать о работе с декораторами в Python, рекомендую почитать по этим ссылкам: devacademy (ru) и Python 3 Patterns, Recipes and Idioms (en)

2016
08 октября, 20:16

Прекрасная статья о том, как программировать на JavaScript, используя только 6 символов. И даже есть ссылка на сервис, который таким образом конвертирует ваш код в совершенно нечитаемый вид.

28 августа, 16:44
Ошибка при запуске Docker после обновления Linux Debian/Ubuntu

После обновления Debian Jessie до testing я обнаружил проблему при запуске Docker. Набрав команду systemctl status docker.service был выведен следующий текст ошибки:

[graphdriver] prior storage driver "aufs" failed: driver not supported Error starting daemon: error initializing graphdriver: driver not supported

Как оказалось, в новых версиях debian была прекращена поставка модуля ядра aufs, так как вместо него в состав ядра была принята файловая система OverlayFS. OverlayFS - это проект SUSE по созданию более прогрессивной замены UnionFS и AUFS.

Основным недостатком ранее существующей файловой системы UnionFS и созданного на её основе ответвления AUFS является излишне усложнённая кодовая база, составляющая примерно 60 тысяч строк кода, не использующая штатную подсистему VFS. Код AUFS и UnionFS очень трудоёмок для сопровождения и не отвечает требованиям к оформлению кода для ядра Linux, что не позволяло включить его в основной состав ядра. Кроме того, производительность и надёжность данных систем оставляет желать лучшего. В рамках проекта OverlayFS предпринята попытка создания компактного, надёжного и высокопроизводительного аналога UnionFS, построенного поверх штатной подсистемы VFS. (opennet.ru)

Замена aufs на overlayfs

Окей, убедили, надо переходить на overlayfs. Чтобы указать Docker, что нужно сменить файловую систему, необходимо создать файл /etc/systemd/system/docker.service со следующим содержанием:

[Service] ExecStart= ExecStart=/usr/bin/docker -H fd:// --storage-driver=overlay

Смысл сего действа вот в чем: создание нового файла /etc/systemd/system/docker.service позволяет перезаписать значение по-умолчанию, расположенное в файле /lib/systemd/system/docker.service, а чтобы docker не ругался на дублирование значения ExecStart, перед заданием нового значения требуется указать ExecStart с пустым новым значением.

Теперь перезапустим docker с помощью команды systemctl daemon-reload

К сожалению, после перехода на другую файловую систему все существующие docker images будут потеряны. Если вы хотите сохранить их, нужно либо загрузиться со старым ядром, либо ещё перед обновлением заранее сохранить их. О том, как это сделать, подробно написано здесь: http://muehe.org/posts/switching-docker-from-aufs-to-devicemapper/

07 июля, 14:20
Snap vs Flatpak

В последнее время в мире GNU/Linux довольно много шума вокруг самодостаточных кроссдистрибутивных пакетов для графических приложений, таких как Snap от Canonical и Flatpak, разрабатываемый участниками Gnome, RedHat и сообществом разработчиков.

Идея создания универсальных не привязанных к конкретному дистрибутиву приложений не нова, ещё в начале 2000-х была начата разработка Autopackage (в 2010 проект был объединён с Listaller), в 2004 вышла первая версия klik (в 2011 году сменил название на PortableLinuxApps, а в 2013 – AppImage).

Немного с другой идеей, не самодостаточными пакетами, но не привязанными к конкретному дистрибутиву и даже операционной системе был также создан примерно (не нашел точной даты) в 2004 году проект 0install (о нём я уже писал заметку).

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

Но уже в 2007 году стартовал проект Listaller, в котором была добавлена песочница для приложений, в 2014 продолжил развитие под названием Limba. А уже в 2015 году был представлен проект xdg-app, в 2016 году переименованный в flatpak. В этом же году Canonical представила SnapLimba прекратила своё существование в пользу Flatpak.

Я старался здесь перечислить все проекты, в которых была попытка создать универсальный формат, но уверен, какие-то из них потерял, но даже без этого список «универсальных» форматов довольно внушительный.

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

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

Конечно, всё дальше — моё имхо, сформированое за пару дней использования обоих инструментов и гугления^W дакдачинья на эту тему, но по сути flatpak и snap не особо отличаются:

  • Песочница для приложений
  • Развертывание приложений не сталкиваясь с файловой ОС
  • Поставка зависимостей в комплекте

Но главные различия кроются в реализации:

В flatpak песочница реализована использованием возможностями контейнеризации ядра Linux, таких как user namespaces и cgroups, у snap используется MAC kernel security module. Честно говоря, я не знаю, что это означает, но ок.

Для настройки прав приложения snap использует Apparmor, flatpak — SELinux.

В flatpak каждое приложене привязано к какому-то рунтайму, чтобы в своём комплекте поставлять только минимум необходимых библиотек, а остальные использовать из заранее подготовленного рунтайма. На данный момент я нашел рунтаймы от Gnome и freedesktop.org, но должен появиться рунтайм и от проекта KDE. В проекте от Canonical же существует только один рунтайм — ubuntu-core.

Snap имеет централизованный магазин приложений, по типу AppStore, в то же время как Flatpak ориентирован на децентрализованную структуру, каждый может запустить свой репозиторий. Замечу, что один из разработчиков Snap представил рабочий прототип решения для распространения Snap пакетов в обход централизованного каталога-магазина, но по-моему реализация выглядит жутко костыльной и сделана только для того, чтобы в случае чего была возможность заявить, что у них тоже можно создавать альтернативные каталоги, но не для практического использования. С другой стороны, из-за децентрализованного характера Flatpak для установки Libreoffice, из которого я сейчас пишу заметку, мне потребовалось написать 6 команд, не считая самой установки Flatpak и запуска приложения. Надеюсь, это временное решение и в будущем установка будет упрощена до максимума. Например, в том же 0install довольно простая установка приложений, где необходимо просто скопировать адрес страницы с приложением в установщик.

Зная историю ubuntu-one, Unity, Mir, и прочих разработок Canonical, ясно, что компания намерена создать свою закрытую экосистему, а если разработки и выходят за границы ubuntu, то они либо имеют закрытый исходный код, либо установка на других дистрибутивах значительно затруднена необходимостью установить огромное количество патчей от ubuntu на сторонние библиотеки. Да, snap уже был портирован на различные дистрибутивы, и я без особых проблем с ним работал на своей Debian системе, однако мне не кажется, что Canonical собирается разрешить использование рунтаймтов, отличных от ubuntu-core, или откроют исходный код сервера, ведь они движутся в другом направлении.

Таким образом, Flatpak и Snap решают одну проблему, но разными путями: Snap пытается идёт путём Ubuntu/Canonical, в то же время как Flatpak пытается предоставить средство для всех в мире GNU/Linux и, может быть, за его пределами.

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

P.S. Спасибо комментатору на reddit за ценную информацию о различиях в этих двух проектах.

17 мая, 18:51

Новый git клиент в копилку git клиентов. Удобный, красивый, бесплатный, кроссплатформенный. gitkraken.com
Написан с использованием Electron, но я с этим уже смирился.

09 марта, 23:10

В сети самые разные отзывы насчёт удаления из firefox группировки вкладок. Я после перехода firefox на australis нашел кнопочку группировки и пытался использовать, но это был кошмар. Не удивлён, что удалили.
В качестве альтернатив предлагаются несколько дополнений и мне очень понравилось дополнение Simplified Tab Groups. Всё же оно не такое интуитивное, как в старой опере, но уж точно удобнее.

23 февраля, 11:31

Заинтересовала js библиотека Intense Image Viewer, предназначенная для просмотра картинок во весь экран. Уверен, она была бы в тему на сайтиках фотографов.

21 января, 21:17

Вот эта новость просто гениальна. Основные пункты, которые я хочу выделить: 1. Создатель JS и ex-руководитель Mozilla 2. Создал свой браузер 3. Который очередной форк Chromium и, конечно же, защищённый 4. Который вырезает встроенную на сайтах рекламу и замечает на свою

18 января, 14:28

Ещё одна невероятно крутая технология, BitTorrent over WebRTC. Получается, уже сейчас можно с одним только браузером поднять p2p сеть и это вполне стабильно работает. Так что это открывает большие возможности для развития децентрализованных систем.

2015
21 декабря, 16:37

На хабр проникла статья об автоматизации сборки модификаций в S.T.A.L.K.E.R. Радует, что люди ещё интересуются этой игрой и продолжают создавать модификации. Ну а я сделал свой шаг в программирование с этой игрой, а вскоре мне стало тесно в проприетарном мире. Но увлечение постапокалипсисом осталось.