Python added support for type hints in 3.5. These are not typing as you may be used to in other languages since they have no effect on the compilation to bytecode nor at runtime, but rather hints for the (tools of the) developer.
The code above doesn’t fail when you call
print_int("foo") even though
n is “typed” as an
int. This is because
n: int is just a hint.
While you can check for type issues by running
mypy by hand, type hints become really
powerful when your editor/IDE supports them.
Types for collections can specify the inner types: a list (
List) that contains strings (
str) would be
In the snippet above, the last line is highlighted as an error in any good IDE, and
mypy would complain about it.
Other container types exist as well, and they can be nested:
Sequence[x] and other
Set[x], one would expect
Tuple[x] to be a hint for a tuple
x. Well… no.
This is confusing at first, but
Tuple[str] types a tuple of a single element of type
str. To add
more elements, you need to type them as well: a pair of ints would be
Tuple[int, int], while a triplet of a string,
a float and a boolean would be
Tuple[str, int, bool].
While tuples can be used as sequences (e.g. for immutable/hashable equivalents to lists), I’d argue that their primary use is for fixed-length representations, such as pairs of results:
In this snippet,
match_object returns a tuple of a list of floats and a list of integers
If you still want to type arbitrary-length homogeneous tuples, there’s a syntax for that:
types a tuple of any length, including 0, that contains only
int elements (and yes,
... is valid in Python).
For this and other interrogations (how to type a generator?), Mypy has a useful type hints cheat sheet.
TL;DR: if you know the size of the tuple, use
Tuple[x, x, x], etc. If you don’t,
Tuple[x, ...], but all elements must be of type
While working with Magento 2.3.6 on Bixoto I hit a weird issue: the
bin/magento command-line tool was always eating all the RAM, even with a simple command:
The issue, as weird as it sounds, is an empty configuration value that causes Magento to end up in an infinite loop.
When I installed Magento on my local machine, I deactivated HTTPS by setting
NULL in the table
core_config_data. This alone is the cause of the issue.
Check in MySQL:
If this shows a line with a
NULL value, either delete it or replace it with some non-null value:
This has been reported to Magento but was closed because “it’s not a bug”. I don’t think
falling in an infinite loop on
--help because some config value is
NULL should really be a
normal behavior, but at least now you know how to solve it.
While following a tutorial to install Virtualbox in order to have
docker working on macOS, I
hit an issue where the
docker-machine create command fails with an error that looks like this:
If you search on the Web, everybody says you have to open the Security & Privacy settings window
and allow the Oracle kernel extensions to run. But I didn’t have it. I tried uninstalling
Virtualbox, re-installing through the official website, reboot, uninstall, re-install with
brew cask but I always had the issue. Some people reported having a failed Virtualbox
installation but mine seemed ok.
I tried the
spctl solution but it didn’t change anything.
In the end, I tried this StackOverflow answer:
It failed, but it told me to check the Security & Privacy setting window. I did, and I had the button everyone was talking about. I enabled the kernel extension, rebooted, and it worked.
Hope this can save some time to anyone having the same issue!
Code-Golf is the art of writing the shortest program in a given language that implements some given algorithm. It started in the 90’s in the Perl community and spread to other languages; there are now languages dedicated to code-golfing and StackExchange has a Q&A website for it.
4clojure is a well-known website to learn Clojure through exercises of increasing difficulty, but it has a lesser-known code-golf challenge which you can enable by clicking on “Leagues” in the top menu. If you check the code-golf checkbox, you then get a score on each problem that is the number of non-whitespace characters of your solution; the smaller the better.
The first thing you’ll note when code-golfing is that the reader syntax for
anonymous functions is a lot shorter than using
Unfortunately you can’t have a reader-syntax function inside another reader-syntax one, so you often have to transform the code not to use anonymous functions.
for is a very powerful tool for that, because it allows you to do the
map, and a lot more, with no function:
On some problems it can even be shorter than using
Some core functions are equivalent in some contexts and so the shorter one can substitute a longer one:
When you must use a long function name in multiple places, it might be shorter
let that function with a one-letter symbol:
Use indexed access on vectors:
Use set literals as functions:
Inverse conditions to use shorter functions:
Inlined code is sometimes shorter:
1 instead of
Use maps instead of
ifs for conditions on equality (this one really makes
the code harder to read):
(click on the image to play it again)
memento_clientwrapper, we can get the closest snapshot of a website at a given date with the following Python code:
Don’t forget to install the
Note this gives us the closest snapshot, so it might not be exactly two weeks ago.
We can use this code to loop using an increasing time delta in order to get snapshots at different times. But we don’t only want to get the URLs. We wants to make a screenshot of each one.
The easiest way to programmatically take a screenshot of a webpage is probably to use Selenium. I used Chrome as a driver; you can either download it from the ChromeDriver website or run the following command if you’re on a Mac with Homebrew:
We also need to install Selenium for Python:
The code is pretty short:
If you run the code above, you should see a Chrome window open, go at the URL
by itself, then close once the page is fully charged. You now have a screenshot
of this page in
stackoverflow_20181119211854.png! However, you’ll quickly
notice the screenshot includes the Wayback Machine’s header over the top of the
This is handy when browsing through snapshots by hand, but not so much when we access them from Python.
Fortunately, we can get a header-less URL by changing it a bit: we can
id_ to the end of the date in order to get the page exactly as it was
when the bot crawled it. However, this means it links to CSS and JS files that
may not exist anymore. We can get a URL to an archived page that has been
slightly modified to replace links with their archived version using
Re-running the code using the modified URL gives us the correct screenshot:
Joining the two bits of code we can make screenshots of a URL at different intervals. You may want to check the images once it’s done to remove inconsistencies. For example, the archived snapshots of Google’s homepage aren’t all in the same language.
Once we have all images, we can generate a gif using Imagemagick:
I used the following parameters:
-delay 50: change frame every 0.5s. The number is in 100th of a second.
-loop 1: loop only once over all the frames. The default is to make an infinite loop but it doesn’t really make sense here.
You may want to play with the
-delay parameter depending on how many images
you have as well as how often the website changes.
I also made a version with Google (~10MB) at 5 frames per second,
-delay 20. I used the same delay
as the StackOverflow gif: at least 5 weeks between each screenshot. You
can see which year the screenshot is from by looking at the bottom of each