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.


~19% 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 2838 / Polars overkill show all rows-cols decorator

Overkill and suboptimal but good enough and makes my jupyter stuff more pleasant

class DDecorator(ContextDecorator):
    """To use:
    DD = DDecorator()
    with DD:
        your pl stuff with shown cols rows
    # or
    DD(your_df) -> display(your_df)
    """

    def __init__(self, ncols=-1, nrows=-1):
        self.ncols = ncols
        self.nrows = nrows

        def_state = pl.Config.state()
        # print(def_state)
        self.d_ncols = def_state["POLARS_FMT_MAX_COLS"]
        self.d_nrows = def_state["POLARS_FMT_MAX_ROWS"]

    def __call__(self, df, all: bool = False, ncols=None, nrows=None):
        ncols = self.ncols if ncols is None else ncols
        nrows = self.nrows if nrows is None else nrows
        if all:
            ncols = -1
            nrows = -1
        with pl.Config(set_tbl_cols=ncols, set_tbl_rows=nrows):
            display(df)

    def __enter__(self):
        pl.Config.set_tbl_rows(self.nrows)
        pl.Config.set_tbl_cols(self.ncols)
        return self

    def __exit__(self, *exc):
        # print("Finishing")
        # default vals
        pl.Config.set_tbl_rows(self.d_nrows)
        pl.Config.set_tbl_cols(self.d_ncols)
        return False


DD = DDecorator(nrows=30, ncols=30)


def describe(df):
    # with DDecorator(ncols=-1):
    with pl.Config(set_tbl_cols=-1):
        itables.show(
            df.describe(percentiles=None), fixedColumns={"start": 1}, scrollX=True
        )

Day 2837 / Misc polars notes

Input

Read multiple CSV files with GLOBS!

Multiple - Polars user guide:

df = pl.read_csv("docs/assets/data/my_many_files_*.csv")

polars.read_csv — Polars documentation actually accepts lists as well!

Utils

Stack helper fn

Essentially transform a df with cols l_metric,t_metric,l_another,t_another into one with cols type(=l or t), metric,another.

def stack_types(
    df: pl.DataFrame,
    types: Sequence[str] = ("l", "t"),
    metrics: Sequence[str] = ("num_words", "num_chars"),
    id_cols: Sequence[str] = (),
    type_key="type",
) -> pl.DataFrame:
    """Stack prefixed metric columns into long format."""
    return pl.concat(
        [
            df.select(
                *id_cols,
                *(c(f"{t}_{m}").alias(m) for m in metrics),
                type=pl.lit(t),
            )
            for t in types
        ]
    ).rename({"type": type_key})

Bits

If then else otherwise nested

polars.when — Polars documentation

  • otherwise() defaults to None
  • The first one is picked if multiple conditions fit
# If multiple fit then the first one is picked
df.with_columns(
    pl.when(pl.col.foo > 2)
    .then(1)
    .when(pl.col.bar > 2)
    .then(4)
    .otherwise(-1)
    .alias("val")
)
df.with_columns(
...     when1 = pl.col.foo > 2,
...     then1 = 1,
...     when2 = pl.col.bar > 2,
...     then2 = 4,
...     otherwise = -1
... )

Filter where None is involved

polars.DataFrame.filter — Polars documentation TLDR: use e.g. ne_missing() instead of != : polars.Expr.eq_missing — Polars documentation

Polars exclude certain columns

https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.exclude.html: df.select(pl.exclude("ba")) for all cols except ba.G

select can take keyword args!

Select two cols except that col2 will be called new_col2:

df.select("some_col", new_col2="col2")

(oh so many pl.with_columns(...alias('new_col2')) will be avoided by this)

Strings

Format strings

.with_columns(
    pl.format(
        "{} [{}]",
        c(LLM_MODEL),
        c(THINKING).cast(pl.String).fill_null("None"),
    ).alias(MODEL_VARIANT)
)

# when ...
pl.concat_str(
	[c(LLM_MODEL), c(THINKING)],
	separator="/",
	ignore_nulls=True,  # single None doesn't None the entire row
).alias(MODEL_VARIANT)
# ...is not enough

# ...or even this to avoid the [{}] part if thinking is null
.with_columns(
	pl.when(c(THINKING).is_null())
	.then(c(LLM_MODEL))
	.otherwise(pl.format("{} [{}]", c(LLM_MODEL), c(THINKING)))
	.alias(MODEL_VARIANT)
)

Gotchas

Count, len and sum over binary values

# this will never work:
(pl.col(effect_col(m)) < 0).count().alias("n_worsened"),
(pl.col(effect_col(m)) < 0).len().alias("n_worsened"),
# do this insead
(pl.col(effect_col(m)) < 0).sum().alias("n_worsened"),

len counts the entire thing, count() only non-null boolean values (todo?) and basically all will become n regardless of condition.

Use sum().

Polars-statistics for tests/significance/bootstrapping

Pareto frontier

Pareto frontier - Wikipedia “is the set of choices where it is impossible to choose another option that is better in some way without being worse in another.”

Outperforming is called Pareto dominance: a solution A dominates (outperforms) B if A is no worse than B in every objective, and better than B in at least one objective

There are algorithms to calculate that

Misc presentation advice

Presentations

Why not put the various scattered advice I get into one place :)

  1. Better less information properly conveyed than speeding through more information of which 0% will be retained
  2. Never ask the audience a question they are not expecting
  3. Pacing is not enough, when the slide is complex pause at the end to give people time to think
    • When doing dry runs, finishing reading a silde and going to the next won’t give a proper time estimate

Plots

  • If you are planning to highlight or add markings to a plot on the slide, leave a color out of the plot itself
    • (for me: no red lines on plots!)

Day 2822 / More seaborn notes

TODO: merge into 230525-1304 Seaborn how-to guide and use right terminology

Titles (figure-level)

(axis-level: sns.relplot, figure-level:sns.catplot)

Simple titles

sns.catplot(..)
plt.title("mytitle")

Titles overlapping facet text

Previously: 230515-2257 seaborn setting titles etc. with matplotlib set Key:

g = sns.catplot(...)

g.set_axis_labels("Width", "Equals (acc.)")

# # not needed if you do tight_layout()
# g.fig.subplots_adjust(top=0.85)

g.fig.suptitle("Masking and breaking words makes everything worse")

plt.tight_layout()
plt.show()

Fuller example from Change Axis Labels, Set Title and Figure Size to Plots with Seaborn - GeeksforGeeks:

  
# Plot scatter plot
g = sns.relplot(data = tips , x = "total_bill" , 
                y = "tip" , col = "time" , 
                hue = "day" , style = "day" , 
                kind = "scatter" )

# Title for the complete figure
g.fig.suptitle("Tips by time of day" ,
               fontsize = 'x-large' , 
               fontweight = 'bold' )

# Adjust subplots so that titles don't overlap
g.fig.subplots_adjust( top = 0.85 )

# Set x-axis and y-axis labels
g.set_axis_labels( "Tip" , "Total Bill (USD)" )

Day 2821 / Python faker alternatives; Mimesis

Previously: the venerable 260826-1558 Faker has providers and locales TIL: Mimesis Structured Data Generation - Mimesis

It’s much better at generating jobs, for one. EDIT: and colors

mim_locale = Locale.EN
generic = Generic(locale=mim_locale)
job = generic.person.occupation()

Supports locales incl. UKR as well! Providers: API - Mimesis

Day 2820 / Vega Altair visualization notes

Config

Top-Level Chart Configuration — Vega-Altair 6.3.0.post4+gb2ca919d documentation All together with .properties on the Chart object itsel: alt.Chart().encode().properties().top_level_configuration_item()

Etc

Composing

References

Day 2803 / Python rich notes

God the documentation is atrocious.

References

In no particular order bits I looked for but couldn’t find

Styles

Border styles

(E.g. for rules etc.): Panel(box=box.DOUBLE_EDGE).

Boxes types: Box — Rich 14.1.0 documentation

(Box — Rich 14.1.0 documentation says:

You can set the border style by importing one of the preset Box objects and setting the box argument in the table constructor.

That tells me nothing about what do I pass to Panel(..., border_style=), I think it’s only the colors etc. from normal style=, including e.g. ‘on blue’ . In the examples only “dim” and “not dim” are used…)

EDIT oh okay border_style='dim' also influences the colors of the title. Okay why not

Day 2795 / Complexipy for code complexity

How complexipy, ty, ruff and prek can improve vibe coding introduced me to GitHub - rohaquinlop/complexipy: Blazingly fast cognitive complexity analysis for Python, written in Rust. · GitHub and it’s really cool!

Show only the failed functions and suggest refactors:

uv run complexipy src --failed --suggest-refactors

Day 2794 / Faker has providers and locales (incl. Ukrainian!)

UKR locale providers: Locale uk_UA — Faker 40.37.0 documentation Nice! (Note to self: mind inflection and agreement!)

Also Faker as providers, some quite smart ones, e.g. faker-healthcare-provider · PyPI that does languages (not UKR sadly) and matching realistic medical data.

Creating a provider is easy: Welcome to Faker’s documentation! — Faker 40.37.0 documentation

Python text wrapping with TextWrap

textwrap — Text wrapping and filling — Python 3.14.7 documentation

Everything You Can Do with Python’s textwrap Module | Martin Heinz | Personal Website & Blog

Poe the task runner

TODO

Previously: 250527-1937 taskfile go-task bits

Poe the Poet. Previously I used 250527-1937 taskfile go-task bits for something similar.

Poe the Poet is a batteries included task runner that works well with poetry or with uv.

Tasks defined in pyproject.toml. Especially neat are (Python) script tasks that allow you to run any importable thingy from your code. 1

Playing with it, current pytest.ini (rel: 260827-2259 Complexipy for code complexity)

[tool.poe.tasks]
test   = "pytest"
test-now = "pytest -m now --pdb"
check-complexity = "uv run complexipy src --failed --suggest-refactors --max-complexity 15"

ty = "uv run ty check src --output-format concise"
fty = "uv run ty check src --output-format concise --fix"

ruff = "uv run ruff check src"
fruff = "uv run ruff check src --fix"
fruff-unsafe = "uv run ruff check src --fix --unsafe-fixes"

black = "uv run black src --check"
fblack = "uv run black src"

  1. (Is this better than adding usual pyproject.toml uv script endpoints? It supports using inputs from other scripts but if you end up doing that you probably may need a real scripting language) ↩︎


Latest post from Blog

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

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 файл
    • 2025-11-09: Phайл.
  2. Damn kids: тупі/кляті/грьобані діти/школота1/малолітки2? Дякую цьому твіту Букви, який дає мені моральне право використовувати слово “школота”, бо нічого інше не клеїлося (“Окаяні дітлахи!")
  3. three-piece-psychology: інтерпретую як невисоку оцінку розвитку внутрішнього світу. Тому: пересічним/шаблонним/банальним/трафаретним3/примітивним/нехитрим/безхитрим; psychology: ‘інтелект’ але не зовсім, мені подобається ‘ментальність’
    • 2025-11-09: хай буде “трафаретна психологія”, можливо там таки оцінка спроб його зрозуміти, не інтелекту
  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, нічого не подобається. Що його рухає/надихає, що у нього всередині, …
    • 2025-11-09: “що ним рухає”, дякую ChatGPT!
  7. underachiever: хай буде “відстаючий”. Хоча пригадую з ЗНО, що суфікси уч/юч обмежені у вживанні, правильніше ВІДСТАЛИЙ мені не подобається.
    • 2025-11-09: “тупий трієчник”, дякую ChatGPT.
  8. junior high or high school: тут додаю драми замість дослівності, тому що все ближче до оригіналу, що я можу придумати, занадто канцеляристично: “я закінчую базову чи повну загальну середню освіту”..?
  9. Ms. Smith:
  10. I’m a smart ass
    • 2025-11-09: “самозакоханий всезнайко”, дякую ChatGPT.
      • “вважає мене розумником хріновим” дуже непоганий другий варіант.
      • … Знайти короткі вирази, які передають “він думає, що я думаю, що я тут найрозумніший” було тяжко.
      • (r/russian давав ще варіанти градусу “умник ебанный”, … ..no, just no. Варіації “має мене за розумника є**ного”, яке підкидало ChatGPT, теж не радували.)
      • Горох взагалі каже, що правильніше “всезнавець, всевідач”4, але я не буду замінювати слово з “абсолютною частотою” 234 на слово з частотою 1 (чи на слово взагалі без частоти і трьома5 результатами в Гуглі)
  11. doesn’t like teaching: оплакую невикористаний варіант від душі “ненавидить себе, дітей, і педагогіку”. Дуже оплакую. Upd: we live once, це занадто ідеально, хай буде!
  12. a refuge from the day-to-day incompetencies is sought
    • 2025-11-09: “невігластва навколо” ➔ “ідіотизму навколо”.
  13. a board is found: мається на увазі електронна дошка оголошень (BBS — Вікіпедія), дід форумів і прадід іміджбордів. Найцікавіше слово для перекладу. Якщо буде “борд” то збережеться драматизм оригіналу, але є шанси, що хтось спутає з іміджбордами. Коли вони були популярні, нормальні люди в Україні їх не називали ніяк, російською були варіанти “доска”, “бибиэска”6. “BBS” був би найпростішим виходом; “електронна дошка оголошень” знову ж таки канцеляризм. По контексту далі очевидно, що мова йде про якесь спілкування, тому хай буде “борд”, принесу в жертву однозначність і зрозумілість милозвучності.
  14. you bet your ass we’re all alike: як же складно підбирати такі речі. Умовні embeddings з ML тут були б в тему. “Дай мені щось на кшталт ‘авжеж’ тільки більш emphatical”. Попередня версія “Авжеж ми всі однакові!”
    1. You bet – phrases: базара нет, по любому, я вас умоляю
    2. Будьте певні7
    3. ЩЕ Б ПАК — СИНОНІМІЯ | Горох — українські словники
      1. Авжеж?8
    4. 2025-11-09: “Ще й як — ми всі однакові!” — знак оклику тут додає енергії англомовного “you bet your ass”
  15. the beauty of the baud: Бод — Вікіпедія Нехай мій (і єдиний можливий) переклад буде всім настільки ж зрозумілим, наскільки мені був зрозумілий оригінал, коли я його читав вперше.
  16. profitteering gluttons
    • 2025-11-09: “ненажерливі бариги” ➔ “жадібні бариги”

Hat tip to:

Random:

Два роки потому

  1. you bet your ass we’re all alike: як же складно підбирати такі речі. Умовні embeddings з ML тут були б в тему. “Дай мені щось на кшталт ‘авжеж’ тільки більш emphatical”

09/11/2025, в світі, де це вже можливо, я повернувся до цього тексту.

Змінив наступне:

  • Дякую ChatGPT за

    • [0]: Ph-айл => Phайл
    • [5]: what makes him tick: “що є причиною його поведінки” ➔ “що ним рухає”
    • [6]: “тупий відстаючий” ➔ “тупий трієчник”
    • “намагаючись заставити нас повірити, що ви це робите для нашого блага, і попри все - це ми тут злочинці.” ➔ “змусити нас повірити […] але злочинці тут — ми.” (ChatGPT підкинуло “змусити” і відповіло на питання, чи треба тире в останньому реченні)
    • [15] “ненажерливі бариги” ➔ “жадібні бариги”
  • [2]: трафаретна ментальність ➔ психологія

  • [10]: “shouldn’t be teaching”: таки використав ідеальне “ненавидить себе, дітей та педагогіку” (було: “не любить викладати”)

  • [11] `невігластва навколо” ➔ “ідіотизму навколо”

  • [13]: “Та можете не сумніватись, що ми всі однакові…” ➔ “Та ще й як — ми всі однакові!”