Writing a Dropbox Cli in Python with Click
I recently decided to lean into using Dropbox as my designated location for long-term storage. I use Joplin for note-taking and I like the way it uses my own Dropbox account to sync data between devices. Since I’ve found myself in a kind of accidental sabbatical, I started writing a command-line interface for Dropbox to keep myself busy. I didn’t plan on writing anything more than glue code, but once I got started I found it fairly easy to stay engaged with the work. I wanted to cherish that programming momentum that seems to come to me only in fits and starts these days. I’ve called the project dbx
and the code is here: https://gitlab.com/soryrawyer/dbx
about the project
This has been my first real experience using Click, and I’ve been very happy so far. I don’t think this is a very complicated application, but even in these cases I usually find myself struggling against a framework. That hasn’t been the case, as I’ve found Click to provide a nice foundation to work with. One feature in particular has been the test runner, which includes an isolated filesystem. I’ve had to make a few adjustments to my file-handling code, but overall it’s been pretty easy to write tests that don’t interfere with my local filesystem.
Something else I didn’t have experience with prior to this project is generating type stubs. Oddly enough, the Dropbox Python SDK doesn’t come with type stubs. I wasn’t thrilled with the amount of “# type: ignore
” comments I was adding, so I set about generating type stubs myself. I tried using pyright to generate stubs, but that seemed to generate incorrect annotations. For example, the generated stubs had None
as the return type for a lot of functions. Another suggestion was to use Dropbox’s own tooling to generate type stubs. Specifically, using their stone tool to generate type information from the API spec. However, I also found this to be inconsistent with the Python SDK, and other developers reported manually editing the type stubs to make it work.
I ended up settling on stubgen
, which is included with mypy
. Once I knew where pipenv
installed the Dropbox Python SDK, I only needed to run stubgen $SDK_PATH -o typings
from the root of my project. Pyright looks in the typings
directory by default, so I didn’t need any extra configuration to pick up the new stubs.
usefulness
I’ve been relying less and less on Spotify for listening to music on my phone, and while the VLC Android app works well enough, there was still the matter of getting files on my phone in the first place. This project was supposed to facilitate that transfer of music from my laptop to my phone, and so far it’s worked really well.
Also, in addition to Joplin, the Remarkable tablet I use for reading has a Dropbox integration. dbx
helps reduce the friction of moving books and papers to that device as well.
Overall, I’m happy with the progress I’ve made. There are some basic commands implemented — ls
, cp
, mkdir
, and rm
— and I’ve been able to use this with relatively little fuss. My next goal for this is to provide some of this functionality as a library and use it to build file transfer pipelines using libraries like youtube-dl
.
I haven’t tested this to see how easy it’d be to install on another machine, but if you want to try it out, please do! Feedback, issue reports, and PRs are all welcome.