Гизила.Блог
40 subscribers
5 photos
1 file
26 links
Download Telegram
Гизила.Блог
Цілу годину сьогодні провів, щоб нормально з'єднати Flask і Next.JS для локальної розробки. Flask був на 5000 порту, Next.JS на 3000. На бекенді роблю редирект на фронтендову сторінку, треба абсолютний шлях localhost:3000, щоб перекинуло на фронт. З фронта…
Нарешті вирішив цю проблему і головне не прийшлося писати нічого свого. Знайшов пару туторіалів, де люди для локальної розробки просто налаштовували nginx і залежності від шляху перекидували на потрібний порт. Власне я лише запхнув це все у docker-compose і написав під власний проект конфіг. Як бонус налаштував https сертифікати для локальної розробки. Тепер у мене і фронт і бек працює разом за єдиною адресою https://localhost.dev/
Гизила.Блог
На минулих вихідних спробував запуситити власний проект на DigitalOcean, використовуючи Dokku, що не платити Heroku в районі 20$ за дуже простий проект. І тепер я точно рекомендую Dokku, якщо хочеться запусити щось невелике і не розбиратися як налаштовувати…
Недавно писав про dokku, інструмент, щоб легко запусити власні веб проекти. Тоді я запускав веб сайт написаний на Flask, HTML генерувася на сервері через шаблони. І мені тоді здавалося, що краще dokku важко, щось придумати. Але на цьому тижні спробував запустити проект з двох частин: Flask для бекенду і Next.js для server side рендерингу HTML. Найбільше не хотілося мати проблем з CORS, піддоменами, абсолютними редиректами і ось цим всім, тому запланував використати досить поширену практику — Nginx буде приймати весь трафік на один домент і за шляхом запиту буде прокидати його на потрібний бекенд. В моєму випадку мені потрібно було перекидати трафік запитів зі шляхом /api/ на Flask, а все інше на Next.js. От тут я й зіткнувся з проблемами, бо в dokku немає стандартних команд, щоб зробити, щось подібне. А серед плагінів я знайшов лише один, який вже 4 роки не підтримується (як буде натхнення, то спробую створити копію і оновити). Витративши купу часу на це, я зробив костиль, де просто перезаписав дефолтний Nginx конфіг на власний 🤷

Мораль одна — немає нічого ідеального
Сьогодні спробував використати XSD схеми для валідації XML і я залишився дуже задоволений. За допомогою схеми декларативно описуєш як має виглядати XML, віддаєш XML зі схемою в бібліотеку для валідації і на виході отримуєш гарантію, що дані мають потрібну тобі форму або ж список детальних помилок, що і де не так. Правда є відчуття, що я ще не зіткнувся зі складними випадками, де схеми не підійдуть. Але для більшості проектів, де структура XML строго задана, це must have інструмент, щоб не писати валідатор XML вашою мовою програмування 🐍.

Поки що помітив лише один мінус — в інтернеті, якісь страшні і доісторичні туторіали про ці схеми. Таке враження, що весь світ перестав користуватися XML.
Шукаю заміну Graphene для створення GraphQL API, тому буду розповідати про різні бібліотеки, які я вважаю перспективними для цих цілей.

Одна з таких бібліотек це ariadne

Плюси:
- всі резолвери є звичайними функціями, які приймають лише два аргументи. В Graphene треба було успадковуватися від класу ObjectType, позначати які поля має об'єкт і сам резовлер писати як метод класу з префіксом resolve_. Для прикладу в Graphene визначення резолвера виглядає так:
class Query(ObjectType):
books = List(Book)

def resolve_boks(root, info, name):
return []


В ariadne
query = QueryType()

@query.field("books")
def get_books(*_):
return []


- має систему розширення і middleware. По правді в Graphene можна було теж додавати middleware, але це було настільки не зручно, що за весь час прийшлося бачити лише один middleware і жодного розширення. Хоча тут довіряю лише обіцянкам розробникам ariadne:
> Open: Ariadne was designed to be modular and open for customization. If you are missing or unhappy with something, extend or easily swap with your own.

- непогана документація, особливо, порівнюючи з документацією в Graphene.

Але й має недоліки. Найжирнішим з них є те що, поки не зрозуміло як розв'язувати проблему N+1 в GraphQL.

Також суб'єктивним мінусом можна вважати, те що ariadne побудований поверх бібліотеки graphql-core (як і Graphene), яка є портованою JS бібліотекою GraphQL.js. В цій бібліотеці навіть проміси з колбек системою портовані з JS. І власне через це дебажити, що відувається під капотом ціє бібліотеки це ще те задоволення.

Пізніше напишу про strawberry і tartiflette
Гизила.Блог
Шукаю заміну Graphene для створення GraphQL API, тому буду розповідати про різні бібліотеки, які я вважаю перспективними для цих цілей. Одна з таких бібліотек це ariadne Плюси: - всі резолвери є звичайними функціями, які приймають лише два аргументи. В Graphene…
Strawberry - це ще одна бібліотека для стоврення GraphQL серверу на Python і мій особистий фаворит серед інших бібліотек. Схема графа задається через анотації типів, дуже схоже на визначення namedtuple чи dataclass в Python. Приклад з документації:

@strawberry.type
class User:
name: str
age: int

@strawberry.type
class Query:
@strawberry.field
def user(self, info) -> User:
return User(name="Patrick", age=100)

schema = strawberry.Schema(query=Query)

З додаткових переваг бібліотеки є плагін для mypy, вбудований функціонал пагінації, завантаження файлів, автентифікація і тд.

Суттєвими недоліками бібліотеки є проблема N+1 запиту і досить бідна документація.

По при деякі недоліки бібліотека дуже мило і перспективно виглядає, тому я віддаю їй 5 з 5 полуниць 🍓🍓🍓🍓🍓 і спробую якось посприяти її розвитку через спонсорство чи розробку. Приклад реального проекту з використанням strawberry можна найти тут.
pytest просто ❤️. Я зробив помилку в назві декоратора @pytest.mark.parameterize, а він підказав мені, що я дурінь і одрукувався:

E   _pytest.mark.MarkerError: 
test_update_document_info has 'parameterize',
spelling should be 'parametrize'

P.S. найшов забавний плагін для pytest pytest-parawtf, який взагалі приймає будь-яке написання цього декоратора:
> Ever wondered how pytest decides to spell parametrise? Was it parameterize? Parametrise? Parametrize? Confused yet? Stop worrying, install this plugin and all variants are valid.
Випадково натрапив на react-pdf — інструмент для генерації PDF з використанням React. Насправді легко можна знайти подібні бібліотеки для генерації PDF під різні мови чи платформи і нічого особливого в цьому немає. Для прикладу для Python є WeasyPrint чи ReportLab. Але react-pdf має одну кілер фічу, через яку варто розказати про нього — PDF може генеруватися як у браузері, так і на сервері. Причому весь прорахунок стилей робить layout engine yoga, який підтримує досить велику підмножину сучасного CSS.

З мого досвіду, коли треба на сервері зберегти щось в PDF, щось що вже рендериться в браузері, то часто піднімають повноцінний браузер на сервері і зберігають сторінку через друк в PDF 😔. А тут можна використовувати один і то й же код і на сервері, і в браузері. Ще не вистачає додаткового режиму рендерингу, де React код перетворювався б у HTML, замість PDF. Це могло б пришвидшити відображення у браузері, а коли потрібно зберегти у PDF, то міняй режим режим рендерингу і зберігай, де завгодно. Тобі було б взагалі ідеально.
Маю ідеальний план вічного заробітку для ІТ-аутсорсу: держава створює тендер на розробку нової системи, бізнес подає заявку з мінімальною ціною для виграшу в тендері (навіть, якщо ця сума не покриє половини витрат). Після перемоги в тендері, компанія розробляє систему згідно з правилами. Але робить API для цієї системи настільки незручним, заплутаним і жахливим, що пару програмістів по ходу розробки звільняються з цієї компанії. Звісно ж не забути написати документацію без прикладів і пояснень.

Далі сісти і чекати, поки до тебе прийдуть компанії за платною консультацією, з приводу інтеграції до цієї системи.

Якщо ви не вмієте писати жахливий API, то можете звернутися до мене за платною консультацією, я покажу приклади в реальному житті і ще підкину пару хитрих ідей 🙃
На днях стало цікаво як на практиці реалізовують безшовний вхід у декілька сервісів за допомогою одного логіна. В теорії я знав, що круті компанії, по типу Google чи Facebook, для цього використовують стандарт OAuth 2.0. Але проблема в тому, що стандарт містить багато деталей, щоб писати реалізацію самостійно з нуля. Тому пішов шукати готові рішення, щоб нічого не писати, але так щоб ні за що й не платити.

Для Python знайшов бібліотеку authlib, в якій є все що потрібно, щоб зробити власні OAuth 1.0/2.0 сервери (зробити вхід під одним логіном у декілька сервісів) або ж підключатися до сторонніх OAuth серверів (вхід за допомогою Facebook чи Twitter). А ще в цій бібліотеці є інтеграція з популярними веб фреймворками Flask, Django, Starlette і FastAPI. (aiohttp немає 😢). Хоча би за це варто зайти до них на github і вліпити їм зірочку.

Також знайшов компанію, яка розробляє вже все готове, для ідентифікації користувача: OAuth2 сервер hydra, сервер авторизації keto і ще щось там. І до цього всього все це опенсорне, сама ж компанія заробляє на консультаціях. Виглядає все круто і є велика підтримка спільноти у цих сервісів.

В цілому хочеться спробувати на практиці, запустити OAuth2 сервер. набити пару шишок, що зрозуміти чи легше писати кожного разу свою автентифікацію чи запустити якийсь опенсорсний сервіс чи взагалі може легше і дешевше заплатити якомусь хмарному провайдеру.
Вже майже рік чекаю поки Safari добавить пітримку gap для flexbox, бо хочеться в одному місці написати відступ і навіть не чіпати стилі дочірніх елементів:
.flex-container {
display: flex;
gap: 10px;
}

замість славнозівсного:
.flex-container {
display: flex;
margin: -5px;
}

.flex-wrapper {
margin: 5px;
}


Зарза за даними з caniuse.com лише 70% користувачів мають браузер з підтримкою gap 😔 і поки основний блокер це Safari в яких ще близько 16% ринку бразуерів.
Для мене кожен раз є відкриттям, що в python тип Decimal опрацьовує float і str по різному
Недавно дізнався, що в AWS S3 є безкоштовний і простий спосіб зекономити гроші. Для зберігання даних пропонується 4 різні класи сховищ, кожен з яких повільніший для зчитування даних і відповідно дешевший за попередній клас. Для прикладу на стандартному класі треба заплатити $0.0245 за гігабайт, той же час наступний клас сховища пропонує $0.0135$ за гігабайт і затримка на доступ до файлу в межах 1мс.

Як бонус цьому всьому можна налаштувати автоматичне перенесення з одного класу в інший, якщо файл не використовувався довгий час і при цьому файл залишиться за старим ключем, тому нічого нічого не прийдеться міняти у своєму коді.
Foreign data wrapper

Недавно читав книгу з кабанчиком про бази даних і там пислаи про таку штуку як foreign data wrapper. Якщо коротко, то це можливість підключити будь-яке сховище даних до бази даних і його аналізувати через SQL запити. Для PostgreSQL є обгортки для ексель файлів, sqlite, csv, kafka, mongo і кучі всього іншого. Весь список можна знайти тут. Поки не придумав де це може бути корисно, та і маю сумніви, що на практиці хтось аткивно користується, але сама можливість так робити це вже цікаво.
Розширення для браузера

Недавно робив друге в своєму житті розширення для браузера і, оскільки стек для розширень звичайний як для веб (JS, HTML і CSS), то хочу поділитися власним досвідом публікації розширень. Мої розширення не збирають ніяких даних і лише автоматизовують, ті дії, що і так вже є на сайті, тому до мене було менше питань зі сторони модераторів розширень, ніж могло б бути. Якщо зберігаєте хоч якісь дані користувача, то будьте готові надати докази «браузерній поліції» для чого вам ці дані потрібні.

Майже всі браузер з недавніх пір почали підтримувати стандарт для розширень, тому можна один раз написати, упакувати і відправляти один і той самий код в каталоги розширень без змін (окрім Safari звісно ж).

Найпростіше публікувати для Firefox: заповнюєш невелику форму, додаєш опис, завантажуєш збірку розширення, один-два дні його вручну перевіряють модератори і публікують, якщо не знайдуть ніяких порушень. Наступні публікації відбувають в автоматичному режимі і публікація нової версії займає менше хвилини. Просять також додати код розширення, якщо збірка містить JS код, який автоматично був згенерований. За весь час модератори Firefox мені ще жодного разу не відмовляли в публікації, тому посилаю мої промені любві до них❤️. Також здається для Firefox розширення можна не завантажувати в магазин, а поширювати на своєму сайті самостійно, але я цей варіант не пробував.

Для публікації в Chrome Web Store потрібно пройти майже ті самі кроки, що й для Firefox, хоча з деякими нюансами. В першу чергу треба додатково написати модераторам мотивацію чому ті чи інші дозволи тобі потрібні. Якщо розширення має працювати для певного хоста, то треба аргументувати, яке ти маєш відношення до цього хоста. Кожна нова версія розширення модеруютьється вручну, запит на модерацію займає 3-4 дні і легко отримати відмову. Для прикладу, причини чому мені відмовляли тричі: не зрозуміло, що робить розширення, немає privacy policy і недостатня аргументація чому розширення повинне мати доступ до хоста. В цілому публікувати в Chrome Web Store втричі важче і повільніше, ніж в каталог Firefox, тому ставлю трійку з п‘яти для Google.

Щоб опублікувати розширення для Safari треба мати MacOS, Xcode і приєднатися до Apple Developer Program за 99$ в рік :classic. Тому для Safari я не осилив публікацію розширення.

Про саме розширення яке робив розкажу трохи згодом окремим дописом.
This media is not supported in your browser
VIEW IN TELEGRAM
Kibana Clicker

Нарешті Google опублікував розширення для браузера, про яке обіцяв розповісти в минулому дописі. Вже встиг про нього розказати на роботі, тому розкажу ще й тут. Це розширення браузера має одну мету — пришвидшити пошук логів в Kibana. Для прикладу, якщо є лог з полем user_id, що має значення 123456789, то розширення вбудовує замість цього значення посилання на сторінкувже з увімкненими фільтром “user_id: 12345678”. Теж саме відбувається для інших значень лога. Раніше, щоб знайти всі логи користувача треба було скопіювати значення user_id, відкрити нову сторінку і сформувати запит руцями. З розширенням процес має скоротитися до одного кроку — перейти по посиланню з вже сформованим запитом.

github, firefox, chrome

Якщо будуть питання, зауваження чи ідеї, то пишіть і коментарях
Hot restarts for everything

Коли щось розробляю, то майже завжди надаю перевагу інструментами, що дозволяють відразу бачити результат, після того, як я щось змінив в коді. Така особливість називається hot reload або hot restart. Для прикладу, коли міняю код мобільного додатку на Flutter, то Flutter автоматично підтягує ці зміни в мобільний додаток і створюється відчуття, що ти модифікуєш додаток на льоту, а не його код.

Одне “але” з цією особливістю, що не всі інструменти підтримують таку можливість. Саме для таких випадків є класна утиліта watchexec, яка вміє слідувати за файлами і перезапускати команду, якщо щось змінилося в тих файлах. Для прикладу, команда, що буде перезапускати python скрипт, якщо відбулися зміни в .py файлах буде виглядати так:

watchexec —exts py -- python main.py

Якщо дехто з вас вже знає про цю утиліту, то, я впевнений, мало хто знає про recamshak/watchexec Docker образ, який місить в собі цю утиліту скомпоновано статично. Тобто, щоб у ваш Docker контейнер додати цю утиліту достатньо буде скопіювати її собі з цього образу і використовувати як я описував раніше.

COPY --from=recamshak/watchexec /watchexec/watchexec /bin/
How to feel rich for free

В університетські роки на якомусь форумі побачив, що є люди, які використовують CapsLock для перемикання мови на клавіатурі. В тих дискусіях люди критикували ту чи іншу OC, якщо в ній були якісь проблеми з налаштуванням перемиканням мов по CapsLock. Тоді мені здалося це дивним аргументом для критики. Але пройшло декілька років і я вже сам першим ділом після встановлення будь-якої OC лізу в Google з питанням:


Use CapsLock to switch keyboard layout {CURRENT_OS}


Підсадив дівчину, підсадився я сам, тому рекомендую і вам. Після першого тижня будете дивуватися чому не зробили це раніше.
.git-blame-ignore-revs

Коли проєкти ростуть, то буває ситуація, що треба масово відформатувати багато файлів: додали новий форматер чи старий змінив форматування, або ж команда вирішила перейти з tab на пробіли для відступів у коді. Проблема таких змін, що git тебе запише, як того хто останній раз змінював код у файлі. Все б то нічого, але команда git blame для такого файлу переважно буде містити одну людину, хоча може бути, що ця людина тільки прийшла на проєкт і їй поставили задачу автоматично відформатувати код.

Тому, щоб git blame містив дійсно тих людей, які міняли код руцями, недавно в git додали параметр --ignore-revs-file. На вхід цей параметр приймає назву файлу зі списком хешів комітів, які треба пропустити і не показувати в історії змін файлу. Щоб кожен раз не вводити цей параметр, його можна визначити в персональних налаштуваннях git для проєкту git config blame.ignoreRevsFile <filename>. На жаль, цей параметр не можна задати на рівні репозиторію, тому кожен, хто буде працювати над кодом і захоче пропустити такі механічні зміни, має виконати цю команду в себе локально.

З іншої сторони, більшість розробників дивним чином домовилися про те, що файли зі списком комітів для ігнорування будуть називатися .git-blame-ignore-revs (приклад Chrominum). Тому можна хоч сьогодні задати глобально ці налаштування на власному компі і додати всіх з кого знімаються звинувачення в погано написаному коді 😬:

git config --global blame.ignoreRevsFile .git-blame-ignore-revs