Skip to content

Instantly share code, notes, and snippets.

View melvinkcx's full-sized avatar

Melvin Koh melvinkcx

View GitHub Profile
@melvinkcx
melvinkcx / celery_app.py
Created September 17, 2020 14:26
Configure Celery To Write Logs To Papertrail
import logging
import os
from celery import Celery
from celery.schedules import crontab
from celery.signals import after_setup_logger, after_setup_task_logger
from django.conf import settings
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
@melvinkcx
melvinkcx / index.js
Created December 22, 2019 07:56
Yielding Python Generator from JS in PyWebView: A Dummy Example
async *genLogs() {
while (true) {
yield await window.pywebview.api.gen_logs();
}
}
const g = genLogs();
(await g.next()).value // 1
(await g.next()).value // 2
@melvinkcx
melvinkcx / release.yml
Created December 23, 2022 06:52
Github Workflow To Create A Release Using Poetry On Tag
name: Release
on:
push:
tags:
- "v*.*.*"
jobs:
build:
runs-on: ubuntu-latest
@melvinkcx
melvinkcx / run_with_wait.py
Created November 18, 2022 04:35
run_with_wait doesn't cancel but wait for all tasks to be completed when the main task is completed, unlike asyncio.run()
from asyncio import coroutines, events, tasks
def run_with_wait(main, *, debug=None):
"""
Difference from asyncio.run():
- asyncio.run() cancels all tasks when `main` is completed.
any tasks created using `asyncio.create_task()` will hence be cancelled.
- run_with_wait() waits for all tasks to be completed using
`run_until_complete()` and `asyncio.tasks.gather()`
@melvinkcx
melvinkcx / Dockerfile
Created October 12, 2022 07:05
Multi-stage Python image with Poetry as deps manager
FROM python:3.10 AS base
WORKDIR /app
RUN curl -sSL https://install.python-poetry.org | python3 -
COPY ./poetry.lock /app/poetry.lock
COPY ./pyproject.toml /app/pyproject.toml
@melvinkcx
melvinkcx / introspect_model_async.py
Created May 25, 2022 02:14
SQLAlchemy Introspect API - Introspecting models using async connection
import logging
from sqlalchemy import MetaData, Table
from sqlalchemy.ext.asyncio import AsyncSession as _AsyncSession
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.orm import sessionmaker
logger = logging.getLogger(__name__)
meta = MetaData()
@melvinkcx
melvinkcx / poetry_to_lambda.sh
Last active May 23, 2022 08:39
Bundle Python app managed with Poetry for AWS lambda
OLDPWD=$(pwd) \
&& cd "$(poetry env info --path)/lib/python3.9/site-packages" \
&& zip -r9 ./app.zip . -x "*.pyc" \
&& mv ./app.zip $OLDPWD \
&& cd $OLDPWD \
&& zip -rg ./app.zip ./app \
&& aws lambda update-function-code --function-name my_function --zip-file fileb://app.zip
# A better alternative is to first upload to an S3 bucket, then update the function
@melvinkcx
melvinkcx / global_errors_in_react.md
Last active January 21, 2022 19:25
Handling Errors Globally In React

Handling Global Errors In React

My Approach: React Context with a custom useError hook

Even though React provides Error Boundaries API, it is not a good candidate, nor is relevant for handling GraphQL query errors.

useError custom hook

import { useState, useCallback } from 'react';
@melvinkcx
melvinkcx / to_snake_case.py
Last active January 13, 2022 05:54
Converting Unicode Sentences To Snake Case In SQL and Python
import re
import unidecode
def to_snake_case(text):
"""
Convert unicode text to snake case
>>> to_snake_case("My favourite dish was raclette.")
@melvinkcx
melvinkcx / fastapi_test_client.py
Created February 15, 2021 09:03
Configurable FastAPI TestClient To Allow Us To Set Cookies Once And For All
from starlette.testclient import TestClient
class CookieConfigurableTestClient(TestClient):
_access_token = None
def set_access_token(self, token):
self._access_token = token
def reset(self):