A handy code sample that I keep forgetting about.
from datetime import datetime, timezone
now = datetime.now(tz=timezone.utc)
print(now.astimezone().isoformat()
A handy code sample that I keep forgetting about.
from datetime import datetime, timezone
now = datetime.now(tz=timezone.utc)
print(now.astimezone().isoformat()
A FastAPI equivalent for verify-events-came-from-stripe.
import os
from http import HTTPStatus
from typing import Annotated
import stripe
from fastapi import Depends, FastAPI, Header, HTTPException, Request
app = FastAPI()
async def get_body(request: Request) -> bytes:
return await request.body()
@app.post("/webhook", status_code=HTTPStatus.NO_CONTENT)
def post_report(
stripe_signature: Annotated[str, Header(alias="stripe-signature")],
body: bytes = Depends(get_body),
) -> None:
endpoint_secret = os.environ["ENDPOINT_SECRET"]
try:
# signature validation
event = stripe.Webhook.construct_event(body, stripe_signature, endpoint_secret)
except ValueError as e:
# Invalid payload
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST) from e
except stripe.error.SignatureVerificationError as e:
# Invalid signature
raise HTTPException(status_code=HTTPStatus.UNPROCESSABLE_ENTITY) from e
print(event)
return
A possible catch, one that I ran into, is that I had FastAPI convert the request.body
to a dictionary in the function parameters (so body: dict
). Then I serialized it to a string for the validation step… and it failed because it was no longer identical to what came in.
During a code review, a colleague, Zachary Paden, asked me why I was calling the typing.cast
function on my variables rather than creating temporary variables just to type hint. Well, just as he didn’t know about cast, I didn’t know that this approach worked. Being the nerdz that we are, he decided to measure the performance of each approach.
Today, at the suggestion of a college (Zachary Paden), I contemplated the idea of migrating my tests using python/monkeypatch to moto. Here I will share my journey and observations.
Continue reading “boto3 – From monkeypatch to moto”In this article, I will explain how to create a pydantic model to validate and create polygons for GIS (geographic information systems).
Continue reading “Creating a pydantic model for GIS polygons”Here is simply how I went about integrating mypy into a few projects. This post assumes you are using git and have a test system in place.
Continue reading “How to integrate mypy in existing projects”For those who are used to using a “basic” virtual environment with virtualenv, poetry can be confusing. Here are some clarifications and tips on using poetry.
Continue reading “Python poetry: Explanations and tips”If you are having problems with AWS lambdas exceeding the 250MB limit, here is a tip that might help.
Continue reading “Minimizing the size of lambdas by avoiding having boto3 and its stubs in the deployment package”On December 12th 2019, poetry v1.0.0 was released. With it, came a bad surprise for me: My CI/CD jobs as well as my Docker image builds started failing.
After investigating, I’ve found out that the password key/value was now missing from the .config/pypoetry/auth.toml
file. Digging some more, I’ve found out that poetry relies on a library called keyring to manage passwords.
Here is what I did to fix the problem.
First, I’ve noticed that poetry falls back to the previous method if keyring returns RuntimeError
when it is called. Nice. It turns out that keyring comes with a backend aptly named “fail” which does that whatever the call is. So, it’s only a matter of configuring it.
As the keyring documentation states it, run python -c "import keyring.util.platform_; print(keyring.util.platform_.config_root())"
to find where to put the configuration file. Then, in that directory, create keyringrc.cfg
and put the following content in it:
[backend]
default-keyring=keyring.backends.fail.Keyring
That’s it. Now you can call poetry config http-basic....
the same way you used to and the password will be stored in auth.toml
like before.
Following some discussions at work and the will of the team to adopt a python code formatter, I set out to explore some of them. No need to say, the contenders had to aim towards pep8 compliance. Here are my findings on three of them.
Continue reading “Python code formatters comparison: Black, autopep8 and YAPF”