Hi!

My name is Serhii Hamotskyi. I work as Machine learning engineer in Leipzig, Germany, but I have a very wide array of interests. This website was born as a way to organize it all.

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


Work journal

Day 1021

Obsidian for zettelkasten-type notes

.. is probably my new obsession, along with getting it to play nicely with Hugo. It’s a closed non-open-source system but files are saved as markdown, has an awesome Android app - everything I’ve ever wanted except openness, basically.

So:

Template to create hugo-compatible front matter in Obsidian:

Templater[^obstempldate] is a community plugin for template stuff, but supports neat things like getting clipboard data, creating files, etc. Additionally supports automatically using templates when creating notes in a folder or in general and a lot of other excellent stuff.

This template gets run manually after I create and name a note. When I run it, it autogenerates Hugo front matter, gets the title from the filename, and puts the cursor in the first tag. The second tag is created from the folder name where the note is located, currently I defined two: it and rl.

---
title: "<% tp.file.title %>"
tags:
  - "zc"
  - "zc/<% tp.file.folder() %>"
  - "<% tp.file.cursor() %>"
fulldate: <% tp.date.now("YYYY-MM-DDTHH:MM:SSZZ") %>
date: <% tp.date.now("YYYY-MM-DD") %>
hidden: false
draft: true
---


Obsidian to Hugo Conversion

I looked at zoni/obsidian-export: Rust library and CLI to export an Obsidian vault to regular Markdown and khalednassar/obyde: A minimal tool to convert a standardly configured Obsidian vault to a Jekyll or Hugo blog., found the latter to be a bit clearer in how it handles assets etc. It requires a date in frontmatter in YYYY-MM-DD format, which I provided.

Day 1018

Python math.isclose() to check for “almost equal”

Had an issue with checking whether a sum of floats sums up to a number, remembering that python floats are ‘special’:

>>> 0.1 + 0.2
0.30000000000000004

Stack overflow1 told me about math.isclose(), works as you’d expect:

assert math.isclose(sum(floats), needed_sum)

  1. python - pytest: assert almost equal - Stack Overflow ↩︎

Day 1015

unittest skip test based on condition

From unittest documentation 1

class MyTestCase(unittest.TestCase):

    @unittest.skipIf(mylib.__version__ < (1, 3), "not supported in this library version")
    def test_format(self):
        # Tests that work for only a certain version of the library.
        pass

  1. unittest — Unit testing framework — Python 3.10.0 documentation ↩︎

Day 1009

Google Meet

You can minimize your own video, and then make the entire window much smaller!

Python strings formatting

Obvious, but: you can declare strings and format them in separate places!

constants.py:

my_string = "Hello my name is {0}"

other_file.py:

from constants import my_string
print(my_string.format("Serhii"))

Pycharm run current unittest binding

<C-S-F10> runs the unittest where the cursor is currently located. Or all of them if located anywhere else in the file.

TODO: set binding to do the same, but debugging.

python - run only some tests from a test suite

I wanted to run only some test files, all except the ones where I needed a GPU. Wrote this:

import subprocess

# Parts of filenames to exclude
large_tests = ['component', 'test_temp']

test_folder = Path(__file__).parent.absolute()
test_files = list(test_folder.glob("test_*.py"))
test_files = [x.name for x in test_files]

for l in large_tests:
  test_files = list(filter(lambda x: l not in x, test_files))

commands = ["python3", "-m", "unittest"] + test_files

subprocess.run(commands, cwd=test_folder)

Notes:

  • Thought this would be a security nightmare, but it’s not1 - unless shell=True is explicitly passed, no shell is called, ergo no shell-command-injection stuff is possible.
  • os.chdir() is nicely replaced by the cwd= parameter, much nicer than what I’d have done previously!

  1. subprocess — Subprocess management — Python 3.10.0 documentation ↩︎

Day 1008

Python typing annotating second-order functions

def my_function(other_function: Callable) -> Callable:
  return other_function

Pycharm run all unit tests in a folder

What I’d do as

cd tests
python3 -m unittest

in Pycharm is right-clicking on a directory in Project view and “Run unittests”

OOP principles

Open/Closed principle: you should be able to open a module/class to add stuff easily, but otherwise you shouldn’t need to touch it for existing stuff.

Python dir

Wrote a line like if dir is not None .., but dir is a builtin! It returns all the names in the current scope.

Pycharm debugging

You can add Watches, values that will be shown and tracked! Nice for debugging stuff that needs values that are deep in other variables

Python unittests run at the end of the class/module

  • class-level:

    • setUpClass(cls) gets called before tests from one class get run, not once per test
    • tearDownClass(cls) gets called before tests from one class get run, not once per test
    • Both need to be class methods, a la:1
        class Test(unittest.TestCase):
            @classmethod
            def setUpClass(cls):
                cls._connection = createExpensiveConnectionObject()
      
  • module-level

    • setUpModule(), tearDownModule()
    • should be implemented as normal functions

    Aaanad if you set any class variables, you can still access them as self.xxx from within the tests!

Python or in arguments

Neat thing seen in detectron default_argument_parser:

def argparser(epilog=None):
  ...
  x = epilog or "here's some text"

Where “here’s some text” is a long string that doesn’t really belong in the function signature.

A really nice pattern, much better than my usual

if x is None:
  x = ...

  1. unittest — Unit testing framework — Python 3.9.7 documentation ↩︎