Google Drive API with Python – Upload & Download a file

For how to authenticate yourself please go watch this video.

You will need a token.json with this content in the root of your project:

{
  "token": "generated_access_token",
  "refresh_token": "generated_refresh_token",
  "token_uri": "https://oauth2.googleapis.com/token",
  "client_id": "your_client_id",
  "client_secret": "your_client_secret",
  "scopes": [
    "https://www.googleapis.com/auth/drive"
  ]
}

I will be using Google’s Quickstart as a foundation for what I am doing.

Read More »

In 2022 – A wishlist of sorts

I want to fully embrace what it means to be a better team manager.

I want to be more effective – resisting pleas of my inner perfectionist and doing what’s right for the business.

I want to use no-code platforms for quick on-the-go solutions – and not waste hours learning docs and coding and debugging and deploying.

I also want to dive more into scaling and advanced deployment techniques.

And more project analytics/trackers – for sure. No matter the size of the project.

I want to make plans B more too. My code can only be as good as it is not failing people.

More than anything, I want to learn more patience.


In 2021 I tried many things professionally that let me bring my career to a whole new level. I see great perspective in my further development as a specialist. In 2022 I strive to see where I lack and work on it.

Anyhow, I am wishing you all an interesting and happy year.

How to move your project from Linux/Mac to a Linux server using SCP

This is purely for the comparison. My recent post was about the same thing but on Windows. Nasty business. And here is a guide for Linux/Mac – it is so much easier.

The difference is that here I use SCP, and for Windows I used SFTP. That is because even after generating the keys with PuTTYgen I could not figure out how to “install” them into PuTTY to use a command pscp -scp (the PuTTY scp) in the Command Prompt. That and the fact that my teammate was more comfortable with GUIs, so I picked the first thing that worked.

Read More »

How to move your project from Windows to a Linux server using SFTP

I abandoned Windows years ago. And I don’t remember the exact moment, but I believe it was something akin to localization issues (my Windows was in Russian).

But in my line of work I deal with different developers on different systems, and lately I have had a situation, where one of my teammates had to use SFTP on Windows… If SFTP on Linux/Mac is a very easy one and done thing, on Windows – not so much.

So I figured out a solution for them.

Disclaimer: On the screenshots the GUIs of the programs are in Russian, but in my text instructions I go through everything in great detail. I also wrote this guide in Russian and translated it with Google Translate, because I feel so lazy right now – I slept like 10 hours without interruption and I feel like I hit gym yesterday (but I actually hit McDonalds).

Read More »

How to add GIF to a static background (PIL + imageio) V.2 – The Better One

My previous version has flaws. It works well for opaque GIFs, but OpenCV is famous for not being good with transparent images. So instead of OpenCV I use imageio for GIF iteration and PIL for adding GIF frames to the static background.

Why do more?

The original algorithm left these artifacts, look at the cyan block on the intersection of GIF frame and a darker abstract part:

The artefact in question
Read More »

Video Generation Journey. Part 1: Making frames (problems 1-4)

Initially, I aimed to make one big post, but I am splitting it up. This Part 1 is about how I made the frames to generate videos from.

Intro

I have been on and off doing this project for a few months. Many things did not work for me – from ffmpeg to sheer OpenCV/ffmpeg installation on Apple M1 systems – and I am not 100% sure what made it work to this day. I plan to put myself in a situation where I have to do it again, and I will make a guide then. However, right now, I can only say that this video tutorial on running native ffmpeg and this guide from OpenCV themselves are good places to start.

The last time I used OpenCV was in 2017 when I worked on my graduate work. Back then, I processed prerecorded videos with no need to worry about audio. So I had some background prior to this project, but I was in no way ready for the ride.

Buckle up!

Table of contents

  • What do I have to create?
  • Limitations
    • Background
    • Phrases
    • Audio
  • Problems
    • Problem 1: GIF on a background
    • Problem 2: Putting text on the image
    • Problem 3: Text wrapping
    • Problem 4: Text blocks positioning
  • Results so far
Read More »

Moving Django to a subpath + Nginx + gunicorn (upd. 18.11.21)

upd. I forgot to include the most important line in the Nginx config. Sorry for that. but it does not work for me anymore. I am confused but I am postponing this for a few days to finish top priority tasks.

Super easy, super fun. Let’s base it on this great guide from Digital Ocean.

Say, the subpath you want is /secret/ 👀.

Add it to Nginx config:

server {
    listen 80;
    server_name server_domain_or_IP;

    location /secret/static/ {
        root /home/sammy/myprojectdir;
    }

    location /secret/ {
        rewrite /api(.*) $1 break;   # !!!!!!!!!!!!!! VERY IMPORTANT
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Then, things we will change in settings.py:

  • in Nginx root means that in the directory it will look for a secret/static/ directory. But now you only have a regular static/.
  • Currently your Django generated static links are all example.com/static, we will change that too.

Your new settings variables will be something like this:

STATIC_URL = '/secret/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'secret/static/'

MEDIA_URL = '/secret/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'secret/media/'
FORCE_SCRIPT_NAME = 'secret'

That’s it. Go check all absolute paths that you wrote down in your project and you are good.

www not working

Before you spend hours of working on Nginx config etc., check your domain’s DNS records.

You need to have a record resembling this:

Type: CNAME

Hostname/Name: http://www.your.website

Value: your.website

TTL (seconds): 3600

And in Nginx you need to capture http://www.your.website (port 80) and redirect it to https://your.website (port 443). Something like this:

server {
    listen 80;
    
    server_name www.your.website
    return 301 https://your.website$request_uri;
}

get_or_create created 2 instances [Sloppy Development]

I am a woman enough to talk about this. I usually don’t let these things happen, but this is such a small thing that let me down on a really high amount of requests.

The statistics of an API I was using showed that at 00:00 UTC we stopped using it altogether.

So, the culprit is the simplest model ever:

class Date(models.Model):
    date = DateField()

And I only ever created it (or altered) like this:

    date, cr = Date.objects.get_or_create(
        day=f'{this_moment.year}-{this_moment.month}-{this_moment.day}'

As it always happens, 4am Sunday it well went to hell – Django create two instances of ‘2021-08-15’.

Eventually every requests that had this line in it just crashed.

Why did this happen? Well, apparently two instances are not supposed to be made.

My friends and I came to a conclusion that with a very high amount of requests Django missed that tiny bit of time between executing get_or_create method and actually writing an instance to PostgreSQL.

Well good thing - I went to bed late, and my team woke me up much earlier than I would wake up.

What is he solution? If the field is meant to be unique, make it unique:

class Date(models.Model):
    date = DateField(unique=True)

Django + Esputnik (part 2) – Error: Cannot transform message content

Long story short, something is wrong with your dynamic tags. Two rules need to be applied:

1. Use ‘ but not “

Right version:

$!data.get(‘your_variable’)

Wrong version:

$!data.get("your_variable") 

2. The tag was broken by another tag

Open the HTML editor of the entire message and Ctrl+F $!data.get(‘.

All the tags need to look like this $!data.get(‘something’). BUT! You may see something like this:

$!data.get(‘something' <span><strong>)

And these <span><strong> are what causing the error.