PythonWise

If it won't be simple, it simply won't be. [Hire me, source code] by Miki Tebeka, CEO, 353Solutions

Tuesday, August 24, 2021

Using gpg for Secrets

I'm using direnv in my project, and sometimes want to set secrets such as AWS_ACCESS_KEY_ID and friends. I usually have a file like:
export AWS_ACCESS_KEY_ID=ABCDEFGHIJK
export AWS_SECRET_ACCESS_KEY=ABCDEFGHIJK/lmnopqrstuvwxyz
export AWS_DEFAULT_REGION=us-east-1
However I don't want to store these values in the clear. The solution I found was to encrypt the file with gpg and then have the following line in the .envrc:
eval $(gpg -qdo- ../../../aws.sh.gpg) 

Tuesday, July 20, 2021

Go's "defer" in pytest (and Python)

 I'm writing a lot of Go & Python these days, and both affect the way I write code.

One feature I really like in Go is defer. Lately, after writing some complicated pytest fixtures, I tried to make simpler and use a "defer" like fixture. Here's what I came with:

Out of the context of pytest, the same idea can become a context manager:


Update: I've published pytest-defer to PyPI.

Thursday, July 09, 2020

Using module __dir__ and __getattr__ for configuration

PEP 562 added support for module level __dir__ and __getitem__
  • __dir__ is called when the built-in dir function is called on the module
  • __getattr__ is called when an attribute is not found via the regular attribute lookup
Let's use this to build an environment based configuration module. 
  • Conviruation values has a value, environment key and a function to convert from str to right type
    • I'm going to use dataclasses and populate values from environment in __post_init__
    • Complex data types (such as list) should be JSON encoded in the environment variables
  • All configuration values with start with the c_ prefix
  • __dir__ will return a list configuration variables without the c_ prefix
  • __getattr__ will add the c_ prefix and will look for the varialbes in globals
We're adding c_ prefix and removing it to bypass the regular attribute lookup mechanism. If we'll call a variable http_port and user will write config.http_port, our __dir__ function won't be called.

Here's the code

Thursday, April 09, 2020

Functions as State Machine (Go)

Let's say you'd like to check that a string is a valid floating point (e.g. "3.14", ".2", "-2.718" ...).
One common techinque to solve these kind of problems is to write a state machine.

In our case, the state machine is:

Instead of writng the state machine a one big function with a lot of state and a bunch of "if" statements, we're going to write states as functions.


To simplify things, the end state is going to be nil for easy comparison.
Then our main function will look like:

An here's how startState looks like


When you write this style of code, states are small and contained function. Easier to test and reason about.

Final comments:
  • You can see the full code here
  • This blog was inspired by the Valid Number problem on leetcode
  • Rob Pike has an excellent "Lexcical Scanning in Go" talk that demonstrates this methon

Wednesday, April 01, 2020

A Twitter Quote Bot on GAE

I like quotes and have an extensive list stored in a text file. I was toying with the idea of making a twitter bot that will post a quote per day. Reading that Google cloud is now offering a Secret Manager rekindled this idea.

The result is @quotamiki (which you should follow ;) It posts one quote per day (9am Asia/Jerusalem). It even has a simple web site.

The code was simple to write, I like how Google App Engine let you focus on writing code and not futz with operations.

You can view the code at https://gitlab.com/tebeka/quotamiki

Thursday, March 05, 2020

Using __getattr__ for nicer configuration API

Typically, you'll read configuration from files (such as YAML) and get them as a dictionary. However in Python you'd like to write config.httpd.port and not config['httpd']['port']

__getattr__ is a hook method that's called by Python when regular attribute lookup fails (not to be confused with the lower level __getattribute__, which is much harder to work with). You can use it to wrap the configuration dictionary. Here's a small example.


Tuesday, February 04, 2020

Adding a timer to Go's "present" tool

Go has a nice present tool which let's you present code and run it. I wanted to use it in my lightning talk at GopherCon Israel. The talk is a quiz and I wanted a timer to show on each quiz slide.

present syntax supports .html directive which lets you add any HTML code to the slide. From there it easy to add a timer. I wrote timer.html below and added .html timer.html to the first slide.

Here's how it looks (bottom left):

Here's the code:

Blog Archive