Things that live here:

  1. Work log, where I note things I feel I'll have to Google later.
  2. Journal, very similar but about non-IT topics.
  3. Blog for rare longer-form posts (last one below).

Feel free to look at what you can find here and enjoy yourself.


~17% of my country is occupied by Russia, and horrible things are happening there. You can help stop this! If you can donate - I contribute to (and fully trust) Come Back Alive and Hospitallers, but there are also other ways to help.


Latest posts from the Work log

Day 2223 / Annotating PDFs with INCEpTION notes

First impressions

  • INCEpTION User Guide

    • Docker works:
      • docker run -it --name inception -p8080:8080 ghcr.io/inception-project/inception:35.1
      • $ docker run -it --name inception -v /srv/inception:/export -p8080:8080 ghcr.io/inception-project/inception:35.1
        • data will be in /srv/inception
  • Creating a project automatically fills it with sample data: Pasted image 20250131164508.png

  • Tagsets

    • Export format is:
    {
      "name" : "BBK",
      "description" : null,
      "language" : null,
      "tags" : [ {
        "tag_name" : "aaa_human_processed",
        "tag_description" : null
      }, {
        "tag_name" : "block",
        "tag_description" : null
      } ],
      "create_tag" : false
    }
    
    • Import format: I can get it do do only txt, one tag per line, first line is name of tagset
  • A layer has to be linked to a feature (string) which then can be linked to a tagset: (INCEpTION User Guide)

    • then you can add keybindings manually
    • and the “editor type” for the tag list is neat, “Radio group” works nicely for tagsets it doesn’t consider small
  • annotations get saved automatically

  • in the viewer, you can set dynamic for annotations differing based on color

Export

  • Admin->Export can
    • export the entire projects
    • project + separately a copy of the anntations

Resources

Day 2220 / Using uv as shebang line and adding requirements

Using uv as your shebang line – Rob Allen (HN comments) and more detailed article on this: Lazy self-installing Python scripts with uv

But especially Defining Python dependencies at the top of the file – Rob Allen and the PEP 723 – Inline script metadata | peps.python.org

You can add uv to the shebang line as

#!/usr/bin/env -S uv run --script

And you can set requirements by adding this under the shebang line:

# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "flickrapi",
# ]
# ///

Then you can uv run sync-flickr-dates.py

Full package:

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "flickrapi",
# ]
# ///
import flickrapi
print("\nI am running")
❯ chmod +x test.py
❯ ./test.py
Installed 11 packages in 134ms

I am running!

Neat!

Day 2214 / Cherry-pick range of commits in git

git - How to cherry-pick multiple commits - Stack Overflow:

For one commit you just pase its hash.
For multiple you list them, in any order.
For a range, you do oldest-latest but add ~, ^ or ~1 to the oldest to include it. Quoting directly from the SO answer:

# A. INCLUDING the beginning_commit
git cherry-pick beginning_commit~..ending_commit
# OR (same as above)
git cherry-pick beginning_commit~1..ending_commit
# OR (same as above)
git cherry-pick beginning_commit^..ending_commit 

# B. NOT including the beginning_commit
git cherry-pick beginning_commit..ending_commit

Day 2213

pipx inject library into app environment

TL;DR pipx inject target_app package_to_inject

  • pipx is awesome, and can install apps in their own virtualenv
  • If you try e.g. pipx psutil it refuses, it’s a library, not an app
    • and tells you to use pip
  • If I want psutil for the MemoryGraph widget in (pipx install-ed) qtile, that doesn’t help
  • What does: pipx inject qtile psutil
❯ pipx inject qtile psutil
  injected package psutil into venv qtile
done! ✨ 🌟 ✨

Kubernetes copying files with rsync and kubectl without ssh access

So, given that kubectl cp was never reliable ever for me, leading to many notes here, incl. 250115-1052 Rancher much better way to copy data to PVCs with various hacks and issues like 250117-1127 Splitting files, 250117-1104 Unzip in alpine is broken issues etc. etc. etc.

For many/large files, I’d have used rsync, for which ssh access is theoretically needed. Not quite!

rsync files to a kubernetes pod - Server Fault

ksync.sh (EDIT Updated by ChatGPT to support files with spaces):

if [ -z "$KRSYNC_STARTED" ]; then
    export KRSYNC_STARTED=true
    exec rsync --blocking-io --rsh "$0" "$@"
fi

# Running as --rsh
namespace=''
pod=$1
shift

# If user uses pod@namespace, rsync passes args as: {us} -l pod namespace ...
if [ "X$pod" = "X-l" ]; then
    pod=$1
    shift
    namespace="-n $1"
    shift
fi

# Execute kubectl with proper quoting
exec kubectl $namespace exec -i "$pod" -- "$@"

Usage is same as rsync basically :

./ksync.sh -av --info=progress2 --stats /local/dir/to/copy/  PODNAME@NAMESPACE:/target/dir/

(Or just --progress for per-file instead of total progress).

Rsync needs to be installed on server for this to work.

For flaky connections (TODO document better): -hvvrPt --timeout1 and while ! rsync ..; do sleep 5; doen 1

Day 2212 / argparse add arbitrary kwargs at the end

If no real config thingy is required/wanted, then this works (stolen from Parsing Dictionary-Like Key-Value Pairs Using Argparse in Python | Sumit’s Space)1:

def parse_args():
    class ParseKwargs(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            setattr(namespace, self.dest, dict())
            for value in values:
                key, value = value.split("=")
                getattr(namespace, self.dest)[key] = value
    parser.add_argument("--no-pics", action="store_true", help="Predict only on videos")
	# ...

    parser.add_argument(
        "-k",
        "--kwargs",
        nargs="*",
        action=ParseKwargs,
        help="Additional inference params, e.g.: batch=128, conf=0.2.",
    )

  1. interesting mix of topics on that website ↩︎

Day 2211 / arch linux low battery notification

#!/bin/bash

BATTINFO=$(acpi -b)
LIM="00:15:00"
if  grep Discharging) && $(echo $BATTINFO | cut -f 5 -d " ") < $LIM ; then
  # DISPLAY=:0.0 /usr/bin/notify-send "low battery" "$BATTINFO"
  dunstify "low battery" "$BATTINFO"
fi

For this, install and run on startup dunst, then cron job for the above.

Day 2209

Unzip in alpine is broken

docker - Why do I get “unzip: short read” when I try to build an image from Dockerfile? - Stack Overflow:

TL;DR alpine’s unzip is busyboxes, and fails for me with

/data/inference_data # unzip rd1.zip
Archive:  rd1.zip
unzip: short read

apk add unzip installs the same real one I have on all other computers, and then it works.

Splitting files

E.g. to upload it somewhere where it’s hard to upload large files

See also: 250117-1104 Unzip in alpine is broken

# split
split -b 2G myfile.zip part_
# back
cat part_* > myfile.zip

Rancher k8s control pods execution nodes

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: kubernetes.io/hostname
                operator: NotIn
                values:
                  - node_to_avoid

(operator: In for the list of the allowed nodes)

Day 2208 / YOLO trainings bits

Related: 250115-1238 Adding wandb to a CLI yolo run

  • Reference are surprisingly hard to find on the website: results - Ultralytics YOLO Docs

  • yolo detect train model=yolo11s.pt data=/data/data/data.yaml project=/data/project/ epochs=500 imgsz=640 device=0,1 name=yolo11s-aug-500epochs-full

  • YOLOv11 sets default batch_size 16, one can set -1 for it to automatically pick one that’s 60% of GPU, or 0.8 to automatically pick one that’s 80% of GPU

  • To decrease verbosity in predictions, verbose=False to model.predict() (and `.track()) works1.

  • Changing imgsz= to something lower may not necessarily make it faster, if a model was trained with a certain size it may predict faster at that size (e.g. OSCF/TrapperAI-v02.2024 predicts at 40+ iterations per second when resized to 640 and ~31 when left to its default 1024pd)

    • Resizing (if provided a single int, not a tuple) works by making the larger side of the image equal to the given one, if padding is needed grey is used(?)
  • Half-life precision (if supported by GPU) is really cool! half=True makes stuff faster (no idea about prediction quality yet)

    • And batch size obviously
  • vid_stride predicts every Nth video frame, was almost going to write that myself

All-in-all I like ultralytics/YOLO

Day 2207

Kubernetes rancher magic pod yaml config to avoid shared memory crashes

I had exotic not enough shared memory crashes, ty GC for giving me these lines I do not yet understand but that seem to work, later I’ll dig into why (TODO)

apiVersion: v1
kind: Pod
metadata:
  name: CHANGEME
  namespace: CHANGEME-ns
spec:
  restartPolicy: Never
  containers:
    - name: sh-temp-yolo-container-3
      image: ultralytics/ultralytics:latest
      command: ["/bin/sh", "-c"]
      args: 
        - "yolo detect train model=yolo11s.pt data=/data/data/data.yaml project=/data/project/ epochs=30 imgsz=640 device=0,1"
      resources:
        requests:
          nvidia.com/gpu: "2" # GPUs for each training run
          ephemeral-storage: "12Gi"
        limits:
          nvidia.com/gpu: "2" # same as requests nvidia.com/gpu
          ephemeral-storage: "14Gi"
      volumeMounts: # Mount the persistent volume
        - name: data
          mountPath: /data
        - name: shared-memory
          mountPath: /dev/shm
  volumes: 
    - name: shared-memory
      emptyDir:
        medium: Memory
    - name: data
      persistentVolumeClaim:
        claimName: sh-temp-yolo-pvc

Both requests AND limits, as well as mount shared memory in volumeMounts + volumes.

Kubernetes / Rancher much better way to copy data to PVCs

apiVersion: v1
kind: Pod
metadata:
  name: temp-pod
  namespace: CHANGEME-ns
spec:
  restartPolicy: Never
  containers:
    - name: temp-pod
      image: alpine:latest # Use a lightweight image
      command: ["sleep", "3600"] # Keep the pod running for 1 hour
      volumeMounts: # Mount the persistent volume
        - name: data
          mountPath: /data
  volumes: # Specify the persistent volume claim
    - name: data
      persistentVolumeClaim:
        claimName: CHANGEME-pvc

So basically trivial temporary pod done specifically to copy stuff to a PVC that auto-kills itself in 1h w/ no need to do anything for this — ty KM for this!1

Then one can happily copy stuff from there using the usual:

❯ kubectl cp CHANGEME-ns/temp-pod:/data/project/train7/ .
# as well as 
kubectl exec -it temp-pod -n CHANGEME-ns -- sh

ADDITIONALLY, I had issues cp ing things larger than 6gb. Reminder to myself that one can tar things or just transfer in separate parts.


  1. See also 240131-1535 Setup for Dockerfiles where you can look around before running for an overkill option for this that I wouldn’t use anymore ever. ↩︎

Git removing untracked broken files

TL;DR:
git clean -d -f .

If a broken clone / switch leaves stray broken files: error: The following untracked working tree files would be overwritten by checkout:, that fixes it.1

Adding wandb to a CLI yolo run

Assuming you’re doing a YOLO run w/

yolo detect train model=yolo11s.pt data=/data/data/data.yaml project=/data/project/ epochs=500 imgsz=640 device=0,1 name=yolo11s-aug-500epochs-full
  • name there becomes training run name in wandb + directory name in /data/projct
    • (project on wandb will be `-data-project-)
  • To enable wandb:
pip install wandb
yolo settings wandb=True
wandb login 

Or if you’re inside an ultralytics:latest Docker container,

apt install -y bash screen
bash
pip install wandb
yolo settings wandb=True
wandb login 
screen 
yolo detect train model=yolo11s.pt data=/data/data/data.yaml project=/data/project/ epochs=500 imgsz=640 device=0,1 name=yolo11s-aug-500epochs-full

Also useful:

# get a model file
wandb artifact get /proje:ject/run_alxxxpy7_model:v0 --root target_director/

Day 2203

Python nested list comprehensions syntax

Nested list comprehensions are a horrible idea because they are hard to parse, and I never understood them, BUT.1

python - How do I make a flat list out of a list of lists? - Stack Overflow has a discussion in the accepted answer about the suggested syntax to flatten lists, and I get it now.

flat_list = [
    x
    for xs in xss
    for x in xs
]

# equivalent to 
flat_list = []

for xs in xss:
    for x in xs:
        flat_list.append(x)

So,

[x for xs in xss for x in xs]

Comments:

I found the syntax hard to understand until I realized you can think of it exactly like nested for loops. for sublist in l: for item in sublist: yield item

[leaf for tree in forest for leaf in tree]

I kept looking here every time I wanted to flatten a list, but this gif is what drove it home: i.sstatic.net/0GoV5.gif 

GIF IN QUESTION, after which it clicked for me: Pasted image 20250111002755.png

The first element is the one that gets returned!

for tree in forest: for leaf in tree: return leaf
[leaf (for tree in forest, for leaf in tree)]
[leaf (for tree in forest for leaf in tree)]
[leaf for tree in forest for leaf in tree]

Found Understanding nested list comprehension syntax in Python — /var/ which expands on this, quoting PEP

It is proposed to allow conditional construction of list literals using for and if clauses. They would nest in the same way for loops and if statements nest now.

It then shows:

for x in non_flat:
    if len(x) > 2
        for y in x:
            y
# equivaent to
>>> [ y for x in non_flat if len(x) > 2 for y in x ]

MIND. BLOWN.

I’m not sure “this requires you to understand Python syntax” is an argument against using a given technique in Python This is about itertools.chain(*list, which is the way to go imo. But still, * is python syntax, otherwise there are more or less readable ways to do thigs and nested comprehensions are rarely worth it


  1. From comment to another answer in that same question that shames me: ↩︎

Poor-man's dark mode bits

  • Qutebrowser:
    :set colors.webpage.darkmode.enabled true Really neat actually! ALSO: colors.webpage.preferred_color_scheme: dark tells websites my preference
  • Nvim: :colorscheme zaibatsu
  • Redshift: redshift -r -P -O 4000 -b 0.3
  • If I’m doing all that, I probably want to mute my speakers as well

Obsidian export HTML

For one-off HTML exports, found the plugin KosmosisDire/obsidian-webpage-export: Export html from single files, canvas pages, or whole vaults. Direct access to the exported HTML files allows you to publish your digital garden anywhere. Focuses on flexibility, features, and style parity.

It exports both the vault and individual pages, and adds things like toc on the left and toggles and optionally file browsing. Much better than the other pandoc-based export plugin that I could not get to work reliably for exporting good-looking HTML


Latest post from Blog

'The Hacker Manifesto', переклад українською

Оригінал: .:: 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], і ви 
називаєте нас злочинцями. Ми досліджуємо... і ви називаєте нас 
злочинцями. Ми шукаємо знання... і ви називаєте нас злочинцями. Ми 
існуємо без кольору шкіри, без національності і без релігійної 
нетерпимості... і ви називаєте нас злочинцями. Ви будуєте атомні бомби, 
ви ведете війни, ви вбиваєте, обманюєте, і брешете нам, намагаючись 
заставити нас повірити, що ви це робите для нашого блага, і попри все - 
це ми тут злочинці.

	Так, я злочинець. Мій злочин - моя допитливість. Мій злочин - 
оцінювати людей по тому, що вони кажуть і думають, а не по тому, як 
вони виглядають. Мій злочин в тому, що я вас перехитрив, і ви мене 
ніколи не пробачите за це.

	Я хакер, і це мій маніфест. Можливо ви зупините мене як особу, але ви 
ніколи не зупините нас всіх... зрештою, ми всі однакові.
	

Замітки:

  1. Ph-айл: worst of both worlds between phile and файл
  2. Damn kids: тупі/кляті/грьобані діти/школота1/малолітки2? Дякую цьому твіту Букви, який дає мені моральне право використовувати слово “школота”, бо нічого інше не клеїлося (“Окаяні дітлахи!")
  3. three-piece-psychology: інтерпретую як невисоку оцінку розвитку внутрішнього світу. Тому: пересічним/шаблонним/банальним/трафаретним3/примітивним/нехитрим/безхитрим; psychology: ‘інтелект’ але не зовсім, мені подобається ‘ментальність’
  4. and 1950’s technobrain: Німецький переклад, який сподобався англіцизмами та дав ідею перекласти technobrain в значенні “знання про компʼютери”, а не слово в слово: Berühmte Manifeste 2 – openPunk
  5. хакер/гакер: Вікіпедія вважає обидва допустимими; сам Авраменко ссилаючись на ті самі правила українського правопису теж вважає обидва допустимими, але все ж любить “г” більше (Хакер чи гакер - експрес-урок - YouTube). А я не можу і не буду. Хакер. I will die on this hill.
  6. what makes him tick: TODO, нічого не подобається. Що його рухає/надихає, що у нього в середині, …
  7. underachiever: хай буде “відстаючий”. Хоча пригадую з ЗНО, що суфікси уч/юч обмежені у вживанні, правильніше ВІДСТАЛИЙ мені не подобається.
  8. junior high or high school: тут додаю драми замість дослівності, тому що все ближче до оригіналу, що я можу придумати, занадто канцеляристично: “я закінчую базову чи повну загальну середню освіту”..?
  9. Ms. Smith:
  10. I’m a smart ass
  11. doesn’t like teaching: оплакую невикористаний варіант від душі “ненавидить себе, дітей, і педагогіку”. Дуже оплакую.
  12. a refuge from the day-to-day incompetencies is sought
  13. a board is found: мається на увазі електронна дошка оголошень (BBS — Вікіпедія), дід форумів і прадід іміджбордів. Найцікавіше слово для перекладу. Якщо буде “борд” то збережеться драматизм оригіналу, але є шанси, що хтось спутає з іміджбордами. Коли вони були популярні, нормальні люди в Україні їх не називали ніяк, російською були варіанти “доска”, “бибиэска”4. “BBS” був би найпростішим виходом; “електронна дошка оголошень” знову ж таки канцеляризм. По контексту далі очевидно, що мова йде про якесь спілкування, тому хай буде “борд”, принесу в жертву однозначність і зрозумілість милозвучності.
  14. you bet your ass we’re all alike: як же складно підбирати такі речі. Умовні embeddings з ML тут були б в тему. “Дай мені щось на кшталт ‘авжеж’ тільки більш emphatical”. Попередня версія “Авжеж ми всі однакові!”
    1. You bet – phrases: базара нет, по любому, я вас умоляю
    2. Будьте певні5
    3. ЩЕ Б ПАК — СИНОНІМІЯ | Горох — українські словники
      1. Авжеж?6
  15. the beauty of the baud: Бод — Вікіпедія Нехай мій (і єдиний можливий) переклад буде всім настільки ж зрозумілим, наскільки мені був зрозумілий оригінал, коли я його читав вперше.
  16. profitteering gluttons

Hat tip to:

Random: