25th March 2022

Coding⚑

Python⚑

Type Hints⚑

• New: Suggest to use `Sequence` over `List`.

Because using `List` could lead to some unexpected errors when combined with type inference. For example:

``````class A: ...
class B(A): ...

lst = [A(), A()]  # Inferred type is List[A]
new_lst = [B(), B()]  # inferred type is List[B]
``````

Possible strategies in such situations are:

• Use an explicit type annotation:

``````new_lst: List[A] = [B(), B()]
lst = new_lst  # OK
``````
• Make a copy of the right hand side:

``````lst = list(new_lst) # Also OK
``````
• Use immutable collections as annotations whenever possible:

``````def f_bad(x: List[A]) -> A:
return x[0]

def f_good(x: Sequence[A]) -> A:
return x[0]
f_good(new_lst) # OK
``````
• Sometimes the types of several variables are related, such as “if x is type A, y is type B, else y is type C”. Basic type hints cannot describe such relationships, making type checking cumbersome or inaccurate. We can instead use `@typing.overload` to represent type relationships properly.

``````from __future__ import annotations

from collections.abc import Sequence

def double(input_: int) -> int:
...

def double(input_: Sequence[int]) -> list[int]:
...

def double(input_: int | Sequence[int]) -> int | list[int]:
if isinstance(input_, Sequence):
return [i * 2 for i in input_]
return input_ * 2
``````

This looks a bit weird at first glance—we are defining double three times! Let’s take it apart.

The first two `@overload` definitions exist only for their type hints. Each definition represents an allowed combination of types. These definitions never run, so their bodies could contain anything, but it’s idiomatic to use Python’s `...` (ellipsis) literal.

The third definition is the actual implementation. In this case, we need to provide type hints that union all the possible types for each variable. Without such hints, Mypy will skip type checking the function body.

When Mypy checks the file, it collects the `@overload` definitions as type hints. It then uses the first non-`@overload` definition as the implementation. All `@overload` definitions must come before the implementation, and multiple implementations are not allowed.

When Python imports the file, the `@overload` definitions create temporary double functions, but each is overridden by the next definition. After importing, only the implementation exists. As a protection against accidentally missing implementations, attempting to call an `@overload` definition will raise a `NotImplementedError`.

`@overload` can represent arbitrarily complex scenarios. For a couple more examples, see the function overloading section of the Mypy docs.

• Use `journalctl -eu docker` to debug

DevOps⚑

Automating Processes⚑

cruft⚑

• Typically a result of hidden binary files in project folder. Maybe you have a hook that initializes the `.git` directory, don't do that.

Operative Systems⚑

Linux⚑

ffmpeg⚑

``````cat *.VOB > output.vob
``````

• Identify the streams

``````ffmpeg -analyzeduration 100M -probesize 100M -i output.vob
``````

Select the streams that you are interested in, imagine that is 1, 3, 4, 5 and 6.

• Encoding

`bash ffmpeg \ -analyzeduration 100M -probesize 100M \ -i output.vob \ -map 0:1 -map 0:3 -map 0:4 -map 0:5 -map 0:6 \ -metadata:s:a:0 language=ita -metadata:s:a:0 title="Italian stereo" \ -metadata:s:a:1 language=eng -metadata:s:a:1 title="English stereo" \ -metadata:s:s:0 language=ita -metadata:s:s:0 title="Italian" \ -metadata:s:s:1 language=eng -metadata:s:s:1 title="English" \ -codec:v libx264 -crf 21 \ -codec:a libmp3lame -qscale:a 2 \ -codec:s copy \ output.mkv`