The optional type annotations in Python is a big and relatively new thing. For the majority of its life, Python didn’t have any good solution for static type checking, and people coming to the language fell in love with it for different reasons. Today’s case study: how many old-school Python developers use type annotations? Specifically, we’ll be looking at the core developers because these are mostly people the most dedicated to the language.| blog.orsinium.dev
All sufficiently big public package registries are a mess full of malware, name squatting, and drama: crates.io has a single user owning names like “any”, “bash”, and “class”. npmjs.com had a drama with left-pad when a single maintainer of a single one-liner package broke the internet. pypi.org appears in tech news monthly with another group of researchers discovering another malware campaign. Today PyPI malware made news yet again, so I decided to take a look at the other side of...| blog.orsinium.dev
The Go standard library is full of bad design choices from the perspective of safety of use. A prime example of that is the blog post Aiming for correctness with types by fasterthanlime. It, among other things, compares the Go stdlib http package to a third-party Rust hyper library. And while some parts that the author covers are due to the nature of Go as a language, most of them, I believe, are a bad design of the specific library and can be fixed without rewriting everything to Rust.| blog.orsinium.dev
This article is an exploration of how to improve error handling in Go. I address here some of the issues while others are left with open questions and some ideas. And, spoiler alert, I do love error handling in Go as it is now. I don’t want to replace it with anything like exceptions, but I want to make it slightly better. I’m going to limit all solutions to what we already have in the language.| blog.orsinium.dev
The package fmt defines GoStringer interface, and I think it doesn’t have recognition it deserves. According to the documentation: GoStringer is implemented by any value that has a GoString method, which defines the Go syntax for that value. The GoString method is used to print values passed as an operand to a %#v format. That means that you can implement GoString() string method on any of your types, and it will be called when the object of this type is formatted using %#v.| blog.orsinium.dev
Dataset First of all, we need a dataset. We could use the Reddit API but it has quite a small number of posts you can retrieve. Luckily, you can find a dump of everything from Reddit at files.pushshift.io/reddit. Let’s download a few datasets: wget https://files.pushshift.io/reddit/submissions/RS_2020-02.zst wget https://files.pushshift.io/reddit/submissions/RS_2020-03.zst Next, we need to read the data and select only subreddits and columns we’re interested in. Every dataset takes a lot ...| blog.orsinium.dev
Linters pyflakes – checks only obvious bugs and never code style. There are no opinionated checks. Pyflakes should be enabled in any project, and all errors must be fixed. pycodestyle – most important code style checker. Controls compatibility with PEP-8 that is standard de-facto for how Python code should look like. Initially, the tool was called pep8, but renamed after Guido’s request. flake8 is the most famous Python linter. First of all, it is a framework allowing you to write custo...| blog.orsinium.dev
Linters The first linter you face coming into Go is go vet. It is a built-in linter targeted mostly at finding bugs rather than code style. Another official linter from the Go core team is golint. This one is targeted at finding not bugs but mostly style issues from the official code review guide and effective go. If you want to catch more bugs and write more effective code, consider running more linters.| blog.orsinium.dev
Python has a colon (:) after all statements that start a new block: if, for, while, def, class, with, else. For example: if a == 1: b = 2 However, the colon looks redundant. Both a machine and a human can understand that a new block started by indentation, and you can’t miss that block anyway. For the example above it could look like this: if a == 1 # SyntaxError b = 2 So, why do we need it?| blog.orsinium.dev
Let’s take for example an incredibly simple code and imagine that it’s incredibly complicated logic. def cat(left, right): """Concatenate two given strings. """ return left + right Tests How can we be sure this code works? No, it’s not obvious. Remember the rules of the game, we have an incredibly complicated realization. So, we can’t say it works or not while we haven’t tested it. def test_cat(): result = cat(left='abc', right='def') assert result == 'abcdef' Now, run pytest:| blog.orsinium.dev
Hi everyone. I’m Gram. Today I wanna talk to you about the bad, the ugly and the good python logging. First, I want to say a few words about logging structure. Loggers expose the interface that application code directly uses. Logger defines set of handlers. Handlers send the log records to the appropriate destination. Handler has list of filters and one formatter. Filters filter log records. Formatters specify the layout of log records in the final output.| blog.orsinium.dev
Go standard library In Go creating of the JSON quite simple, just pass any data in json.Marshal, and you get the bytes with JSON. But parsing of JSON is painful, especially when you want only one field that located deep in the source JSON. You have to create all maps and structs for all places where located fields that you need. See full example on Go by Example. Make it better gjson – allows you to get any data from JSON without difficult conversions and type-casting.| blog.orsinium.dev
(This post was originally published in @pythonetc telegram channel) The round function rounds a number to a given precision in decimal digits. >>> round(1.2) 1 >>> round(1.8) 2 >>> round(1.228, 1) 1.2 Also you can set up negative precision: >>> round(413.77, -1) 410.0 >>> round(413.77, -2) 400.0 round returns value of input number’s type: >>> type(round(2, 1)) >>> type(round(2.0, 1)) >>> type(round(Decimal(2), 1)) >>> type(round(Fraction(2), 1))| blog.orsinium.dev
Standard library Ok, there is how you can parse and format date or time string into time.Time object: t = time.Parse(format, timeString) t.Format(format) And this format is the most strange thing in Go. There is an example of a format: Mon, 02 Jan 2006 15:04:05 -0700 My first thought was “Wow, smart Go can get an example of a time string as format”. No. If you pass “2007” instead of “2006” your program will fail in runtime.| blog.orsinium.dev
I think, collections.Counter is the most magic and powerful container in Python. This is smart and beautiful multiset realization. Let’s have a look at what Counter can do. Basic usage Basic usage for Counter is to count some element (for example, words) in a sequence and get N most popular. from collections import Counter words = 'to be or not to be'.split() c = Counter(words) # Counter({'to': 2, 'be': 2, 'or': 1, 'not': 1}) c.| blog.orsinium.dev
How to create your own iterator or iterable? In Python, we have two complementary terms: iterator and iterable. An iterable is an object that has an __iter__ method which returns an iterator, or which defines a __getitem__ method that can take sequential indexes starting from zero (and raises an IndexError when the indexes are no longer valid). So, you get the iterator from the iterable object. By default __iter__ always returns self.| blog.orsinium.dev
I love decoupling. This makes the project maintaining easier. We have 2 main ways to do it: Git submodules. This is a good conception but sometimes very confusable. Also, you must commit updates in parent project for each submodule changing. Packaging. I think this solution is better because you already use many packages in your project. You can easily package your project and explain this concept to any junior. This article about creating python package without pain.| blog.orsinium.dev
“Always write documentation for everything” seems like advice that you can give anyone in any situation and it will make everything better. It’s not. There is a cost and risk associated with every line of documentation you write, and this is exactly what this blog post is about. When I say “documentation”, I mean all forms of it, including README, Markdown files, docstrings, and code comments. Why your documentation sucks It requires maintenance.| blog.orsinium.dev