In the middle of the desert you can say anything you want
import this
A coworker reminded be of this gem; quoting him:
The order is important. My favourite one is ’explicit is better than implciit'
Had a big repo, wanted to clone only some folders.
The setup below automatically fetched the subfolders I added to the sparse-checkout set.
git clone --filter=blob:none --no-checkout --branch main ssh://git@me.me/my/repo.git
cd myrepo
git sparse-checkout init --cone
git sparse-checkout set "activitywatch" "friends" ".task" ".timewarrior"
https://gohugo.io/tools/search/
It boils down to creating an index (json) then using something to search in it client side
Once an index is built, Lunr seems the way to do with this: https://lunrjs.com/docs/lunr.Query.html#~Clause
It seems flexible enough, including ability to search inside taxonomies.
~/.dotfiles for stow to work# essentials
sudo apt install cowsay fortune-mod
sudo apt install vim-gtk3 # for clipboard support
# wm clipboard
sudo apt install i3
sudo apt installxdotool maim xclip zenity
# misc
sudo apt install jq tldr silversearcher-ag rofi xscreensaver
sudo apt install blueman
sudo apt install tree stow
sudo apt install fish
sudo apt install taskwarrior timewarrior
sudo apt install arandr, autorandr
# if needed ensurepip
sudo apt install python3.12-venv
sudo apt install git git-lfs
sudo apt install tig
sudo apt install pavucontrol
#sudo apt install kitty
sudo apt install alacritty
sudo apt install htop
sudo apt install ncal # cal command
uv task installgem install friendsbrew install hugobrew install go-taskbrew install asciiquariumenpx pagefind (for hugo)chsh /usr/bin/fishtlp if it’s a laptop~/.fonts should work, subdirectories possible
fc-cache -v tells you which dirs it goes throughfc-cache -f installssudo apt install fonts-firacodealias cal="ncal -w -A1 -M" # week starts on monday, 1 months from now, show weeks
From SO1, if both are JSON serializable objects, you can use json:
from json import loads, dumps
from collections import OrderedDict
def to_dict(input_ordered_dict):
return loads(dumps(input_ordered_dict))
Scripting Commands — Qtile 0.1.dev50+ga708c8c.d20211209 documentation has a lot more interesting stuff than the ones exposed through “vanilla” config, finally figured out how to use them:
def test(qtile):
qtile.cmd_to_layout_index(0)
# ...
Key([mod, ctrl], "apostrophe", lazy.function(test))
It’s in the docu1 but I missed its significance on first read, then saw hints in a github config2.
The qtile object passed as the first argument is exactly the QTile from scripting.
To parametrize it, you have to let it return a callable function:
def switch_to(ly_id: int):
def cb(qtile):
qtile.cmd_to_layout_index(ly_id)
return cb
# ...
Key([mod, ctrl], "apostrophe", lazy.function(switch_to(0))),
I don’t see this mentioned in the docu, but the attributes can be found in the source of libqtile.core.manager — Qtile 0.1.dev50+ga708c8c.d20211209 documentation.
If you mess up config.py and restart qtile and most of your keybindings aren’t working, if you’re lucky you still have a terminal open. From it, you can fix config.py, then restart via qtile shell -> restart().
Get screenshotting working through a hotkey. I need to screenshot an area of the screen, put the screenshot in a folder, and immediately open it.
In i3 had
bindsym Mod3+s --release exec scrot -s -e 'mv $f ~/s/screenshots && eog ~/s/screenshots/$f'
Nothing I tried worked (didn’t do anything weird):
Key([mod], "s", lazy.spawn(CONFIG_LOCATION + "screenshot.sh"))
Tracked it down to two main issues:
scrot works, scrot -s doesn’t. (Running the shell script directly from shell was fine!)# this works
scrot -u -e 'thunar $f' "/tmp/shot.png"
# this doesn't
scrot -u -e 'thunar $f' "$SCREENSHOT_PATH/shot.png"
Decided to leave the first one alone, scrot -u gets the currently selected window, which generally is good enough for me.
The second one - first rewrote the script to get passed the target path as positional variable (surprisingly it worked!), then decided to do it python-only. As a bonus, copies the screenshot url to the clipboard.
# definition
copy_command = 'bash -c "echo {0} | xclip -selection c"'
# ...
def take_screenshot():
SCREENSHOT_FILENAME = datetime.now().strftime("qtile_%y%m%d-%H%M%S%z")+"-$w$h.png"
screenshot_path = D.SCREENSHOT_DIR +"/"+ SCREENSHOT_FILENAME
command = f"scrot -u -e 'thunar $f && {Commands.copy_command.format('$f')}' {screenshot_path}"
return command
#usage
Key([mod], "s", lazy.spawn(Commands.take_screenshot()))
(qtile-dotfiles/config.py at master · justinesmithies/qtile-dotfiles has escrotum as python module, errored out during install in the qtile venv and segfaulted on first run when installed outside of it.)
To add an item for the WM to the options shown on gdm startup:
.desktop file to /usr/share/xsessions:[Desktop Entry]
Name=qtile
Comment=Qtile
Exec=/home/me/.dotfiles/qtile/.config/qtile/startup.sh
Type=Application
X-LightDM-DesktopName=qtile
DesktopNames=qtile
Keywords=tiling;wm;windowmanager;window;manager;
sudo systemctl restart gdm.service1Before that I tried killing gdm3 and X but it didn’t work. ↩︎
(From a python-worshop I attended)
asserts (vs. unittests’ self.assertEqual()...)
def test_whatever():
# ....
assert foo == bar
Fixtures are useful bits you don’t want to repeat every time, like connecting to a database etc.
It’s a function, that may or may not take arguments, that might or might not return something.
Tests can request a fixture, and it’s basically done like this:
@pytest.fixture
def my_fixture():
return "fix"
def test_with_fixture(my_fixture):
assert my_fixture == "fix"
# fixtures inside other fixtures
@pytest.fixture
def next_fixture(my_fixture):
return my_fixture + "fix"
They are run independently for each test, to ensure that tests are as separated as possible. There are ways to define their scope, but it’s rarely used.
You can also use them to change settings like logging, by adding a fixture that changes etc.
“By using the pytest.mark helper you can easily set metadata on your test functions” 1
#@pytest.mark.skip(reason="there's a good reason")
@pytest.mark.skipif(pytorch.cuda.is_available(), reason="there's a good reason")
def test_always_ski():
assert False
That way you don’t have to do anything inside the test and based on python environment.
# simple marks
@pytest.mark.whatever
def test_whatever():
pass
# complex marks (and defined beforehand)
cuda = pytest.mark.skipif(True, reason="...")
@cuda
def test_require_cuda():
assert False
@pytest.mark.one
@cuda
def test_whatever():
Assuming @pytest.mark.gpu:
python3 -m "not gpu"
python3 -m "gpu"
Recommended, to keep track of them and get stuff like pytest --markers etc.
In pyproject.toml:
[tool.pytest.ini_options]
markers = [
"gpu: marks test which require a gpu"
]
Replace some functions, including ones deep inside code. Lives inside the pypy package pytest-mock · PyPI.
You can patch calls, objects, etc.
from pytest_mock import MockerFixture
def test_mock(mocker: MockerFixture) -> None:
env_mock = mocker.patch("os.environ.get")
os.environ.get("something")
assert env_mock.call_count == 1
# Do stuff to dictionaries:
mocker.patch.dict("os.environ", {"sth": "test"})
assert os.environ.get("sth") == "test"
assert os.environ.get("not_there") == None
# classes, function calls, etc
TODO - does this work for class instances created after the mock?
mocker.spy
Sample from documentation:
def test_spy_method(mocker):
class Foo(object):
def bar(self, v):
return v * 2
foo = Foo()
spy = mocker.spy(foo, 'bar')
assert foo.bar(21) == 42
spy.assert_called_once_with(21)
assert spy.spy_return == 42
pytest test_mod.py and pytest testing/pytest -m mark, pytest -m "not mark"pytest -k "MyClass and not method would run TestMyClass.test_something but not TestMyClass.test_method_somethingpytest test_mod.py::test_func or pytest test_mod.py::TestClass::test_methodEDIT: Deprecate looponfail · Issue #826 · pytest-dev/pytest-xdist deprecated :( no replacement
pytest-xdist package allows to do pytest --loop-on-fail, which keeps looping tests and you can see the test results in real time
logger.warning("test") inside tests doesn’t get shown by default, but you can enable this in pytest results:
[tool.pytest.ini_options]
log_cli = true
log_cli_level = "DEBUG"
You can change it in single tests: caplog.set_level(logging.DEBUG)
This is useful if you’re fixing a specific bug and want more logging on a specific test.