Getting started with GraphQL and Python most of the documentation is focused on the basics: basic queries, filtering using pre-built libraries and so forth. This is great for quick “Hello World” APIs, but there isn’t much discussion for best practices that discuss how to build out larger APIs, testing, or maintenance. Perhaps it’s just too early in the Python-GraphQL story for the best practices to have been fully established and documented.

Introductory GraphQL examples online don’t really require much testing of the resolver specifically. This is because these examples  just return the results of a Django Queryset directly. For those types of fields executing a full query is usually enough. But how to you handle more complex resolvers, ones that have some processing?

Accessing your resolver directly from a unit test is difficult and cumbersome. To properly test a resolver, you’re going to need to  split the parts that warrant independent testing into their own functions / classes. Then once it’s split, you can pass the required input for processing, and return the results.

However passing or returning Graphene objects to your functions will make testing them difficult in much of the same way that calling your resolver outside of a GraphQL request is difficult: you can’t access the attribute values directly – they must be resolved.

blog = Blog(title="my title")
assert blog.title === "my title" # fail

Where Blog is a Graphene object, the above test will fail. As blog.title will not be a String as you’d think, but rather a graphene wrapper that will eventually return “my title” when passed through the GraphQL machine.

There’s two ways to work around this:

  1. Pass in `namedtuples`  that match attribute for attribute your Graphene objects in their place. This is will become a maintenance headache as each time your object changes, you’ll need to also update your named tuples to match.
  2. Pass/return primitive values into your functions and box them into GraphQL objects in your resolver directly before return.

I’ve done both in my code and think that the second method is a best practice when writing GraphQL apis.

By passing the values from graphene as primitives to your processing functions your code is no longer tied directly to graphene directly. You can change frameworks and re-use the same code.

It’s also easier to write tests as you pass in common objects like dict and int which are quite easy to assert equality and simpler to reason about.

Takeaways:

  1. Break your logic out of your resolver and into specialized functions / classes.
  2. Pass/return primitive or other such values from these functions to maximize reuse.

When sharing photos at work most of my co-workers would simply post a link to Google Photos in our company Slack. As an iCloud user, I thought my photos were only visible on my Mac or iPhone – machines logged in to my Apple account and setup to sync photos. So if I wanted to share photos with co-workers on Slack, I had to either upload them to Flickr or upload them directly into Slack. I always just uploaded them into Slack.

I just realized today that I can view all of my photos from the web via iCloud Photos. What’s more is I can share photos with a URL just like my co-workers have been with Google Photos. The shared link also expires after 1 month, which is a nice additional security / privacy feature.

Knowing that I can access my photos outside of Apple devices eases my mind. While I can’t ever see myself switching to Android from iOS, I could see myself using a Thinkpad + Linux for my desktop computing needs.

My website has recently come full circle back to WordPress. It’s been a number of years since I’ve used WordPress. The last time was probably in college on the cheapest shared host I could find. I avoided coming back to WordPress because I didn’t want to maintain a server; I fiddle enough with them at work. Already being a Digital Ocean customer, the 1-Click setup/hardened server seemed like the best way to go. 

I quickly got it configured with all of the IndieWeb plugins to facilitate back-feeding content that I create on other platforms onto my website. The final step starting to use MarsEdit, my old favorite blog editor. Except it couldn’t connect to my website.

Turns out the reason is that the majority of WordPress security issues stem from bots abusing the xmlrpc api and the digital ocean install blocks it at a low level by default. Disabling this block on the server allows programs to use the xmlrpc api and hence MarsEdit to work. Execute the following commands to disable the xmlrpc block.

sudo a2disconf block-xmlrpc
sudo systemctl reload apache2

Back when Macs came with modems built in, the one feature that I thought was super cool but never used was the Print to Remote Fax feature. It was one of those features like “Duh, of course. We can create PDFs. Naturally we can send them over the modem for printing.”

The PDF file format is a ubiquitous file format and the only real way to guarantee document layout and display, no matter the device or operating system used to view it . Python, being a language that excels at data processing and manipulation, naturally has a lot of tools for working with PDF files to generate reports. This post is a brief introduction to the tools that are available and the tasks they work best for.

Wand

Wand is a set of Python bindings for do-it-all ImageMagick library. As such it really a Swiss-army knife for PDF (and image) manipulation and generation. In the context of PDF, ImageMagick (and therefore Wand) is mostly a frontend for GhostScript.

Its API is quite Pythonic and can help you split, convert, and even draw on PDF files. Wand is perfect for manipulating existing PDFs and doing light editing on them.

ReportLab

ReportLab is a commercial/open-source PDF generation library. If you’re making complex PDFs from scratch this is the library you should pick. Period.

PikePDF

PikePDF is a PDF manipulation library based on qpdf. As its underpinnings are written in C++ it’s super fast. Unlike other python pdf libraries, PikePDF supports unlocking encrypted / password protected PDFs.

PikePDF also lets you explore the internal structure of a PDF document, which make it a perfect tool for debugging problem PDFs and extracting content/images.

The APIs are very Pythonic, and let you work with manipulate pages / page order like a regular list. PikePDF is also great for repairing and prepping PDF to be manipulated by Wand.

Pillow

Pillow is a PDF library, but it supports exporting images to PDF, making it a powerful tool in your Python PDF toolbox.

While there’s some overlap of functionality Wand in terms of image editing capabilities, it’s more focused on editing images, rather than transforming and converting images. Pillow is an indispensable tool when working with any user-supplied images in your PDF workflow.

Conclusion

There is no single PDF tool in Python that fits all needs, all the time. These libraries can, and are, often used in conjunction with one another to quickly and easily generate PDFs on demand. However, depending on how you combine them, there can be some issues resulting in large file sizes and slow generation times. I’ll cover these gotchas in future posts.

On a project at work I’ve been learning GraphQL. I’m in charge of both developing the backend ( using the wonderful graphene-django package) and the frontend ( using Typescript / Vue.js / axios ) for this specific feature.

After wrapping my head around GraphQL and getting a basic endpoint working I wanted to write some tests to ensure that filtering and other requirements are working as expected.

For a proper End-to-end test I’d usually setup a client and post a json dictionary or such. With End-to-end GraphQL tests you need to send actual GraphQL queries, which makes sense but it feels a bit like SQL Injection.

Below is how I’ve settled organizing and writing my GraphQL tests.

tests/
├── __init__.py
├── conftest.py
├── test_myapp/
│   └── test_schema.py

Because the graphql client will be reused across the django site, I added a global fixture that will automatically load mty project’s schema.

# tests/conftest.py
@pytest.fixture
def graphql_client():
from myproject.schema import schema
from graphene.test import Client
return Client(schema)

In this example I’m testing that I’m filtering data as expected when passing a search parameter.

For setup, first I write a query as its own fixture so I can re-use it throughout the test and it’s clear exactly what is going to be run. Second, I make sure the query uses variables instead of hard-coded values when querying so I can change the input depending on the test. Third, setup a model_bakery fixture for data that I expect to find.

import pytest
from model_bakery import baker

@pytest.mark.django_db
class TestMyModelData:
@pytest.fixture
def query(self):
return """
query testGetMyModel($searchParam: String!){
myModelData(searchParam: $searchParam) {
totalCount
}
}"""

@pytest.fixture
def my_model(self):
baker.make(
"myapp.MyModel",
total_count="20", # Decimal field
)

def test_none_response(self, graphql_client, query, my_model):
executed = graphql_client.execute(query, variables={"searchParam": "skittles"})
assert executed == {"data": {"myModelData": None}}

def test_filters_usage(self, graphql_client, query, my_model):
params = {"searchParam": "skittles"}
executed = graphql_client.execute(query, variables=params)
assert executed == {
"data": {
"myModelData": {
"totalCount": 20
}
}
}

Executing each test I simply pass my query and required variables for the test/query. In this I’m testing the same query twice: once with and one without a searchParameter. My expectation is that I get no results without a search term and data when to my graphql_client fixture.

As the return value from our client is a dictionary, I can simply assert my expecte results with the actual results. If something changes I’ll know immediately.

Using the techniques above I can easily add new tests for my GraphQL endpoint as the available changes or bugs are found.

When testing in Django there’s two basic ways to make an End-to-End test for your view: use the test client to send a request to the server or create a fake request object and manually call your view function.

One isn’t “better” than the other, but I’ve come to prefer using the mock client over the fake request for the following reasons:

  1. Client tests hit the entire stack of code before executing your view allowing you to catch any conflicts with a middleware or settings and your view.
  2. Url Path tests come for free. When testing with fake request objects you can put any path you’d like in there and it will execute missing that bad merge where your url config change removing an endpoint.
  3. It’s (slightly) easier to reason about. If I’m writing a test to confirm X happens when Y is posted I make Y and post it rather than making an object that pretends Y was posted.
  4. It removes the friction to refactor your views. As long as the url stays the same, you can rename and move your view however you’d like without changing any of the tests. This makes it easier to create a more consistent codebase e.g. some views use the verb “save” while others use “register”.