Blog

My thoughts and experiments.

© 2023. Dmitry Dolgov All rights reserved.

Use an exception instead of the NaN

This is a small notice about a very useful trick. I often have to deal with computations, because the CFD is the part of my activity. And one of the annoying problem in this kind of research is when after many hours of computations you got a Not A Number result, caused by a stupid mistake. It would be nice, if a computation was interrupted by the NaN.

From bash to fish

I’m doing a small revolution in my environment from time to time. I think “hey, a cool stuff”, take a deep breath and doing something new. And this is story about my migration from the bash to the fish shell.

Let’s see, what says the official tutorial:

fish is a fully-equipped command line shell (like bash or zsh) that is smart and user-friendly. fish supports powerful features like syntax highlighting, autosuggestions, and tab completions that just work, with nothing to learn or configure. If you want to make your command line more productive, more useful, and more fun, without learning a bunch of arcane syntax and configuration options, then fish might be just what you’re looking for!

And this is almost true =) But there is another concrete reason, why I like fish shell:

  • Search by history (as an autocomplete by tab)
  • More intuitive and clean configuration files
  • Vim mode support

Little guide about the gnuchess

I’m at the beginning of my journey into the world of gnuchess. Its interface is a slightly tricky, than I’ve expected, but I was interested. So I’ve decided to make some notes about this.

GNU Chess performs at the senior master/weak international master strength of 2500+ on the Elo rating system

I don’t know, what does this mean really, but sounds cool =)

It is often used in conjunction with a GUI program such as XBoard or glChess

No, it’s not our way. Let’s try to use original teminal-based client (more terminal for the terminal god, mwuahahahaha =).

Another strange thing - an endless paginator

A little bit about my new program-frankenstein. Now it is an endless Paginator for Django. It sounds crazy, isn’t?

Standart Django Paginator uses the count() function for the verification of page number. It is converted to the SELECT COUNT(*) ... query, of course. But as I was explained (I really don’t know, maybe it’s just an exaggeration - you can post your opinion in the commentaries), this is not a such lightweight query, as we want for the paginated rest api, because of the MVCC in PostgreSQL.

How we can avoid the extra COUNT(*) query? Don’t panic, we can trick the Django.

First of all we need to disable count parameter from the api response. We can introduce a custom pagination serializer:

# serializers.py
class CustomPaginationSerializer(BasePaginationSerializer):
    next = NextPageField(source='*')
    previous = PreviousPageField(source='*')

# api.py
class SomeListView(generics.ListAPIView):
    model = SomeModel
    serializer_class = SomeSerializerClass
    pagination_serializer_class = CustomPaginationSerializer

The next our move - disable the page number verification. This can be done by the custom paginator class:

class CustomPaginator(Paginator):
    """ HACK: To avoid unneseccary `SELECT COUNT(*) ...`
        paginator has an infinity page number and a count of elements.
    """
    def _get_num_pages(self):
        """
        Returns the total number of pages.
        """
        return float('inf')

    num_pages = property(_get_num_pages)

    def _get_count(self):
        """
        Returns the total number of objects, across all pages.
        """
        return float('inf')

    count = property(_get_count)

    def _get_page(self, *args, **kwargs):
        return CustomPage(*args, **kwargs)


class SomeListView(generics.ListAPIView):
    model = SomeModel
    serializer_class = SomeSerializerClass
    pagination_serializer_class = CustomPaginationSerializer
    paginator_class = CustomPaginator

Oh, goodness - we introduced the infinity number of the pages and the infinity number of elements… But we want also the correct next/prev links, so one more detail:

class CustomPage(Page):
    def has_next(self):
        """ HACK: Select object_list + 1 element
            to verify next page existense.
        """
        low = self.object_list.query.__dict__['low_mark']
        high = self.object_list.query.__dict__['high_mark']
        self.object_list.query.clear_limits()
        self.object_list.query.set_limits(low=low, high=high+1)

        try:
            # len is used only for small portions of data (one page)
            if len(self.object_list) <= self.paginator.per_page:
                return False

            return True
        finally:
            # restore initial object_list count
            self.object_list = self.object_list[:(high-low)]

This solution looks very questionable, but exciting for me. If you have something to say about this - welcome! =)