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.
The serverless documentation indicates how to share the ids of an API Gateway, but the technique described there seems to work only for a new deployment. (In my case, following this technique created a 2nd empty API Gateway whose ids were shared, which was, unsurprisingly, not fulfilling my needs).
Here is how to do it for an existing deployment.
Continue reading “Serverless: How to share the ids of an existing API Gateway”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”Last April, I wrote a post about managing boto3 in deployed packages. (See Minimizing the size of lambdas by avoiding having boto3 and its stubs in the deployment package). This approach works when all dependencies can be set in the development section.
But, what about when dependencies are required in production? For example, we recently had to deploy a lambda that depends on awswrangler. So the technique suggested in the previous post did not work. Here I will cover a different approach that allows to remove boto3 from the package to be deployed in the example context. It is however less flexible and based on a specific technology: serverless.
Continue reading “Minimize the size of lambdas by deleting boto3 from the deployment package”I recently decided to publish my articles in French and in English. First, I had to find and test plugins in order to choose one. So I spent some time, more than I expected, to make it work locally through Docker. Since I encountered some pitfalls, I decided to share the recipe.
Continue reading “Recipe: Run a local copy of a WordPress site with Docker”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”