Day 2695 / Merge and rearrange pages from multiple PDF
Tiny neat app that shows pages from all PDFs and allows you to rearrange the order, does one thing and does it wonderfully!
My name is Serhii Hamotskyi, welcome to my personal website!
It was created as a way to organize information about all the things I'm interested in. The main parts are listed on the right.
Tiny neat app that shows pages from all PDFs and allows you to rearrange the order, does one thing and does it wonderfully!
Prodigy · An annotation tool for AI, Machine Learning & NLP
First seen in Anshu Kiran Sharma - PhD Student Computer Science, Natural Language Processing’s “Once upon a kernel” @ LREC 2026
Related: Likert scale
ducaale/xh: Friendly and fast tool for sending HTTP requests o
# from README
xh http://localhost:3000/users # resolves to http://localhost:3000/users
xh localhost:3000/users # resolves to http://localhost:3000/users
xh :3000/users # resolves to http://localhost:3000/users
xh :/users # resolves to http://localhost:80/users
xh example.com # resolves to http://example.com
xh ://example.com # resolves to http://example.com
python - How to make a dict from an enum? - Stack Overflow
# Source - https://stackoverflow.com/a/60451617
# Posted by Chris Doyle
# Retrieved 2026-04-09, License - CC BY-SA 4.0
from enum import Enum
class Shake(Enum):
VANILLA = "vanilla"
CHOCOLATE = "choc"
COOKIES = "cookie"
MINT = "mint"
dct = {i.name: i.value for i in Shake}
print(dct)
NiceGUI is freaking awesome.
Resources
Useful examples
props('inline') for inline, remove for vertical; dense exists# somewhere
def create() -> None:
@ui.page('/a')
def page_a():
with theme.frame('- Page A -'):
message('Page A')
ui.label('This page is defined in a function.')
from somewhere import create
# Example 2: use a function to move the whole page creation into a separate file
# in main.py
function_example.create()
OK I think I got it! In e.g. Select | Quasar Framework look for “slots” then you can use them thus1:
sel = ui.select(
list(items),
value=item,
)
with sel.add_slot("after"):
ui.button(icon="description").props("flat no-caps").on(
"click",
lambda e: ui.navigate.to(f"/bp/{whatever}"),
)
table = ui.table()#...
with table.add_slot("body-cell-ColumnName"):
with table.cell("ColumnName"):
# button w/ cell text
ui.button().props("""
:innerHTML="props.value"
""").on(
"click",
js_handler="() => emit(props.row.SomeColumnName)",
handler=lambda e: ui.navigate.to(f"/sth/{e.args}"), # e.args is cell content
)
# conditionals
.props(""" flat no-caps
:label="props.value !== 'N/A' ? props.value : ''"
""")
with ui.link(target="/sd"):
ui.button("Show", icon="description")
with ui.link(target=target_link).classes("no-underline"):
ui.item_label("look ma no underline!")
Ref: Badge: Floating - Quasar Playground but that’s quasar-heavy. Strangely not mentioned in the official quasar docs either. After playing with this this is the python solution:
# remove the floating prop and add one of these classes.
# Removing the prop is useful if using e.g. both top-left and top-right
# then they are on an identicafl height
ui.badge(faiss_dist_str, color="light-blue-10").props(
# "floating"
).classes("absolute-top-left")
ui.table(rows=rows).props("flat bordered").on(
"row-click",
lambda e: ui.navigate.to(f"/pr/{e.args[1]['ISIN']}"),
)
The row-click event comes from quasar: https://quasar.dev/vue-components/table#qtable-api
ui.run(..., fastapi_docs=True) to make documentation available
nicegui/examples/api_requests/main.py at main · zauberzeug/nicegui
async def show_new_quote():
async with httpx.AsyncClient() as client:
response = await client.get('https://zenquotes.io/api/quotes')
quote = random.choice(response.json())['q']
label.text = f'“{quote}”'
From the FAQ:
# (..) app.on_startup(setup)
# def setup():
# if CFG.debug_mode:
import asyncio
loop = asyncio.get_running_loop()
loop.set_debug(True)
loop.slow_callback_duration = 0.05
ui.upload(
auto_upload=True, on_upload=lambda e: handle_upload(e)
).classes("max-w-full")
async def handle_upload(e: events.UploadEventArguments):
with tempfile.NamedTemporaryFile(delete=False, prefix="uns") as tmp:
save_path = Path(tmp.name)
await e.file.save(save_path)
return save_path
element.run_method('focus')
focuses the element, I could connect this to ui.keyboard | NiceGUI to do nice keyboard-centric focus of important fields!
Ref: element.run_method(‘focus’) not working · Issue #1092 · zauberzeug/nicegui (not documented elsewhere I could find)
Validating in real time based on a pydantic BaseModel!: Real-Time Form Validation in Python Using Pydantic | by Aman Deep | Medium
Using a variable globally defined outside a function creates issues. E.g. globally WHAT=‘ever’ and then inside a function. TODO better description.
I know enough German to judge but not enough to write grammatically myself, and this is a pattern I don’t want to forget.
This is SO MUCH BETTER than anything else I’ve used for this! For very short snippets it’s golden
For the main file, see: 240116-1701 LaTeX best practices
[review/final] etc.\setlength{\itemsep}{0pt} \setlength{\parskip}{0pt} and friends\setlength{\belowcaptionskip}{0}
\setlength{\abovecaptionskip}{10pt}1 <- default values\looseness-1TODOs in the text!\bottomrules helps if distance between table and caption too small\mbox to avoid breaks, \- within word to mark break wordsexist [1,3]!\TODO and any custom commands/macros you created\enquote{} everywhere~ is \textasciitilde: check any estimate numbers (~50%)!% is \%; check all percentages!\ is \textbackslash-,--,--- are the safest — look and remove pasted UTF8 ones\references (Figure~\ref{fig:somefig})I wrote this debugging some metrics, bad code but I don’t want it to die. Shows formulas for Precision/Recall/F-Score based on number of TP TN FP FN.
Depends only on rich, runnable w/ uv through 250128-2149 Using uv as shebang line.
Usage: uv run prftset.py tp tn fp fn
# /// script
# dependencies = [
# "rich",
# "pdbpp", # ви цього варті
# ]
# ///
from rich import print
from rich.layout import Layout
from rich.table import Table
import argparse
def get_scores(tp, tn, fp, fn) -> dict[str, int | float | str | None]:
"""Calculate precision, recall, and F1 score from true positives, true negatives, false positives, and false negatives."""
precision = tp / (tp + fp) if (tp + fp) > 0 else None
recall = tp / (tp + fn) if (tp + fn) > 0 else None
f1_score = (
2 * (precision * recall) / (precision + recall)
if precision is not None and recall is not None and (precision + recall) > 0
else None
)
accuracy = (tp + tn) / (tp + tn + fp + fn) if (tp + tn + fp + fn) > 0 else None
f_precision = float(f"{precision:.3f}") if precision is not None else "N/A"
f_recall = float(f"{recall:.3f}") if recall is not None else "N/A"
f_f1_score = float(f"{f1_score:.3f}") if f1_score is not None else "N/A"
total_ds = tp + tn + fp + fn
res = {
"TP": tp,
"TN": tn,
"FP": fp,
"FN": fn,
"total": total_ds,
"P ": f_precision,
"R ": f_recall,
"F ": f_f1_score,
"A ": float(f"{accuracy:.3f}") if accuracy is not None else "N/A",
# "A ": accuracy,
}
return res
def use_table(tp, tn, fp, fn, precision, recall, accuracy):
total = tp + tn + fp + fn
total_positive = tp + fn
total_negative = tn + fp
table_tn = Table()
table_tn.add_column("TP", justify="center", style="green")
table_tn.add_column("TN", justify="center", style="green underline italic")
table_tn.add_column("FP", justify="center", style="red")
table_tn.add_column("FN", justify="center", style="red underline italic")
table_tn.add_column("sum/+/-", justify="right", style="cyan")
table_tn.add_row(
f"[bold green]{str(tp)}[/bold green]",
f"[bold green]{str(tn)}[/bold green]",
f"[bold red]{str(fp)}[/bold red]",
f"[bold red]{str(fn)}[/bold red]",
f"[bold cyan]{str(total)}[/bold cyan]="
+ f"[bold green]{str(total_positive)}[/bold green]+"
+ f"[bold red]{str(total_negative)}[/bold red]",
)
table = Table()
table.add_column("", justify="right", style="cyan", no_wrap=True)
table.add_column("Formula", justify="center", style="magenta")
table.add_column("=>", justify="center", style="magenta")
table.add_column("Value", justify="center", style="magenta")
table.add_row(
"",
f"TP=[bold green]{str(tp)}[/bold green]",
f"[bold yellow]{str(tp)}[/bold yellow]",
"",
)
table.add_row(
"Pre",
"_" * (len(str(tp)) + len(str(fp)) + 6),
"___",
f"P=[bold yellow]{precision}[/bold yellow]",
)
table.add_row(
"",
f"TP=[bold green]{str(tp)}[/bold green] + FP=[bold red underline italic]{str(fp)}[/bold red underline italic]",
f"[bold yellow]{str((tp + fp))}[/bold yellow]",
"",
)
table.add_section()
table.add_row(
"",
f"TP=[bold green]{str(tp)}[/bold green]",
f"[bold yellow]{str(tp)}[/bold yellow]",
"",
)
table.add_row("Rec", "______________", "", f"R=[bold yellow]{recall}[/bold yellow]")
table.add_row(
"",
f"TP=[bold green]{str(tp)}[/bold green] + FN=[bold red underline italic]{str(fn)}[/bold red underline italic]",
f"[bold yellow]{str((tp + fn))}[/bold yellow]",
"",
)
table.add_section()
# Accuracy
table.add_row(
"",
f"TP=[bold green]{str(tp)}[/bold green] + TN=[bold green underline italic]{str(tn)}[/bold green underline italic]",
f"[bold yellow]{str((tp + tn))}[/bold yellow]",
"",
)
table.add_row(
"Acc",
"______________________________",
"",
f"A=[bold yellow]{accuracy}[/bold yellow]",
)
table.add_row(
"",
f"TP=[bold green]{str(tp)}[/bold green] + TN=[bold green underline italic]{str(tn)}[/bold green underline italic] + FP=[bold red]{str(fp)}[/bold red] + FN=[bold red underline italic]{str(fn)}[/bold red underline italic]",
f"[bold yellow]{str((tp + tn + fp + fn))}[/bold yellow]",
"",
)
print(table)
print(table_tn)
def pretty_scores(scores: dict[str, int | float | str | None], draw=True):
tp, tn, fp, fn = scores["TP"], scores["TN"], scores["FP"], scores["FN"]
precision, recall, f1_score = scores["P "], scores["R "], scores["F "]
accuracy = scores["A "]
# print( f"| TP: {scores['TP']}, TN: {scores['TN']}, FP: {scores['FP']}, FN: {scores['FN']} | ")
# print(
# f"| Precision: {scores['P ']}, Recall: {scores['R ']}, F1 Score: {scores['F ']} |"
# )
print(
f"Precision: [bold cyan]P[/bold cyan] = [bold green]{tp}[/bold green] / ([bold green]{tp}[/bold green] + [bold red]{fp}[/bold red]) = [bold yellow]{precision}[/bold yellow]"
)
print(
f"Recall: [bold cyan]R[/bold cyan] = [bold green]{tp}[/bold green] / ([bold green]{tp}[/bold green] + [bold red]{fn}[/bold red]) = [bold yellow]{recall}[/bold yellow]"
)
print(
f"F1 Score: [bold cyan]F1[/bold cyan] = 2 * ([bold yellow]{precision}[/bold yellow] * [bold yellow]{recall}[/bold yellow]) / ([bold yellow]{precision}[/bold yellow] + [bold yellow]{recall}[/bold yellow]) = [bold magenta]{f1_score}[/bold magenta]"
)
print(
f"Accuracy: [bold cyan]A[/bold cyan] = ([bold green]{tp}[/bold green] + [bold green]{tn}[/bold green]) / ([bold green]{tp}[/bold green] + [bold green]{tn}[/bold green] + [bold red]{fp}[/bold red] + [bold red]{fn}[/bold red]) = [bold yellow]{scores['A ']}[/bold yellow]"
)
# use_layout(tp, tn, fp, fn, precision, recall)
use_table(tp, tn, fp, fn, precision, recall, accuracy)
def main():
args = parse_args()
# Example usage
# tp = 100
# tn = 50
# fp = 10
# fn = 5
tp = args.tp
tn = args.tn
fp = args.fp
fn = args.fn
scores = get_scores(tp, tn, fp, fn)
pretty_scores(scores)
def parse_args():
parser = argparse.ArgumentParser(
description="Calculate precision, recall, and F1 score."
)
# use positional arguments for tp, tn, fp, fn
parser.add_argument("tp", type=int, help="True Positives", default=0)
parser.add_argument("tn", type=int, help="True Negatives", default=0)
parser.add_argument("fp", type=int, help="False Positives", default=0)
parser.add_argument("fn", type=int, help="False Negatives", default=0)
# parser.add_argument("--tp", type=int, required=True, help="True Positives")
# parser.add_argument("--tn", type=int, required=True, help="True Negatives")
# parser.add_argument("--fp", type=int, required=True, help="False Positives")
# parser.add_argument("--fn", type=int, required=True, help="False Negatives")
return parser.parse_args()
if __name__ == "__main__":
main()
kubectl delete pod <> --nowTy KM (https://github.com/kkmarv) for the following, quoting verbatim:
The expected behaviour of kubectl delete heavily depends on its arguments. There are 4 possible but wrongly documented options. I’ve tried to compile different sources into this list:
kubectl delete pod <> will first send a SIGTERM, then a SIGKILL after X seconds (depends on the gracePeriods set by your pod)kubectl delete pod <> --grace-period=X (X>0) will first send a SIGTERM, then a SIGKILL after X secskubectl delete pod <> --now is equivalent to kubectl delete pod <> --grace-period=1There’s also --force
Where things are possible to go wrong. It immediately deletes the pod from etcd, which will NOT kill the pod. It will too wait for the grace period before sending a SIGKILL. But even then it is not guaranteed that resources will be freed. There is even a warning in kubectl delete --help about this. Only use this when there is no other way to kill a pod.
The force flag also allows to specify --grace-period=0 which will simply default to the grace period defined by the pod, effectively doing nothing since this is also the default behaviour.
Оригінал: .:: Phrack Magazine ::.
Контекст: Маніфест хакера — Вікіпедія / Hacker Manifesto - Wikipedia
Існуючий дуже класний переклад, не відкривав, поки не закінчив свій: Маніфест хакера | Hacker’s Manifesto | webKnjaZ: be a LifeHacker
==Phrack Inc.==
Том I, випуск 7, Phайл[0] 3 з 10
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Наступне було написано невдовзі після мого арешту...
\/\Совість хакера/\/
автор:
+++The Mentor+++
8 січня 1986р.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Сьогодні ще одного спіймали, пишуть у всіх газетах. "Кібер-скандал:
підлітку повідомили про підозру", "Кіберзлочинця затримали після
проникнення в систему банку".
Тупа школота[1], вони всі однакові.
Та чи ви, з вашою трафаретною психологією[2] та знаннями
інформатики зразка першої половини пʼятидесятих[3], коли-небудь дивилися
в душу хакера? [4] Чи вас колись цікавило, що ним рухає[5],
які сили на нього впливали, що його сформувало?
Я хакер, ласкаво прошу у мій світ...
Мій світ почався ще зі школи... Я розумніший за більшість інших
дітей, і дурниці, які нам викладають, мені набридають.
Тупий трієчник[6], вони всі однакові.
Восьмий, девʼятий, десятий, одинадцятий клас[7]. В пʼятнадцятий
раз слухаю, як вчителька пояснює, як скорочувати дроби. Мені все ясно. "Ні,
Вікторія Миколаївна[8], я не написав проміжні кроки, я розвʼязав все усно..."
Тупий підліток. Мабуть списав. Всі вони такі.
Сьогодні я зробив відкриття. Я знайшов компʼютер. Ха, почекай-но, це круто.
Він робить те, що я від нього хочу. І якщо він помиляється, це тому, що
помилився я. А не тому що він мене не любить...
Або відчуває від мене загрозу...
Або вважає мене самозакоханим всезнайком[9]...
Або ненавидить себе, дітей, та педагогіку[10]...
Тупий підліток. Він постійно тільки грає в свої ігри. Всі вони такі...
Потім це відбулось... відчинились двері в світ... несучись телефонною
лінією як героїн венами наркомана, надсилається електронний пульс,
шукається спасіння від ідіотизму навколо...[11] Знаходиться борд[12].
"Це воно... це те, до чого я належу..."
Я з усіма тут знайомий... попри те, що я з ними ніколи не
зустрічався, не розмовляв, і колись можливо більше нічого не чутиму про
них... Я їх всіх знаю...
Тупий підліток. Знову займає телефонну лінію... Вони всі однакові.
Та ще й як — ми всі однакові! [13] Нас годували
дитячими сумішами з ложки, коли ми хотіли стейк... а ті куски мʼяса, які
до нас все ж потрапляли, були вже пережовані і без смаку. Над нами
панували садисти, або нас ігнорували байдужі. Для тих, хто хотіли чомусь
нас навчити, ми були вдячними учнями, але їх було як краплин дощу в
пустелі.
Цей світ зараз наш... світ електрона і комутатора, світ краси
бода[14]. Ми користуємося існуючою послугою не платячи за те, що могло б
бути дуже дешевим, якби ним не завідували жадібні бариги[15], і ви
називаєте нас злочинцями. Ми досліджуємо... і ви називаєте нас
злочинцями. Ми шукаємо знання... і ви називаєте нас злочинцями. Ми
існуємо без кольору шкіри, без національності і без релігійної
нетерпимості... і ви називаєте нас злочинцями. Ви будуєте атомні бомби,
ви ведете війни, ви вбиваєте, обманюєте, і брешете нам, намагаючись
змусити нас повірити, що ви це робите для нашого блага, але злочинці тут — ми.
Так, я злочинець. Мій злочин - моя допитливість. Мій злочин -
оцінювати людей по тому, що вони кажуть і думають, а не по тому, як
вони виглядають. Мій злочин в тому, що я вас перехитрив, і ви мене
ніколи не пробачите за це.
Я хакер, і це мій маніфест. Можливо ви зупините мене як особу, але ви
ніколи не зупините нас всіх... зрештою, ми всі однакові.
Замітки:
Hat tip to:
Головне, щоб слова не були занадто новими: КОМП’ЮТЕР — СЛОВОВЖИВАННЯ | Горох — українські словники:
Компʼютер
Правильніше: верстак
(Хоча можна ще цікавіше: Комп’ютер - Як перекладається слово Комп’ютер українською - Словотвір)
Random:
- you bet your ass we’re all alike: як же складно підбирати такі речі. Умовні embeddings з ML тут були б в тему. “Дай мені щось на кшталт ‘авжеж’ тільки більш emphatical”
09/11/2025, в світі, де це вже можливо, я повернувся до цього тексту.
Змінив наступне:
Дякую ChatGPT за
[0]: Ph-айл => Phайл[5]: what makes him tick: “що є причиною його поведінки” ➔ “що ним рухає”[6]: “тупий відстаючий” ➔ “тупий трієчник”[15] “ненажерливі бариги” ➔ “жадібні бариги”[2]: трафаретна ментальність ➔ психологія
[10]: “shouldn’t be teaching”: таки використав ідеальне “ненавидить себе, дітей та педагогіку” (було: “не любить викладати”)
[11] `невігластва навколо” ➔ “ідіотизму навколо”
[13]: “Та можете не сумніватись, що ми всі однакові…” ➔ “Та ще й як — ми всі однакові!”
(1) Букви on X: “@donikroman Пане, Ви знову з матами, як школота ¯_(ツ)_/¯ Зауваження, до слова, правильне, українською мовою, а не “на українській мові”, це калька з російської. Може б варто почати з такого? https://t.co/LEEEIX9Bwd” / X ↩︎
„підліток“ синоніми, антоніми, відмінки та тлумачення слова ↩︎
ВСЕЗНАЙКО — СЛОВОВЖИВАННЯ зслається на “Мова – не калька: словник української мови”. Частота звідси. ↩︎ ↩︎