Published my first PyPI package!
I wrote a lot of code over the last few years and loved every moment of it. Ideas and delivery sure move at a faster pace compared to my wet-lab days. But so do expectations. It’s still the same mindset but with different tools: plan experiments, tweak things until they work robustly, and of course build tools to make the process easier next time. The only difference is that I no longer handle enzymes or edit DNA. These days I build models, run simulations on remote machines, and of course: I write a lot of Python.

Remember that bit about expectations? Here’s a mantra that tends to help:
You should never have to solve the same problem twice.
To prevent having to solve problems twice and as my projects grew, every folder naturally morphed into a modular pipeline. Two problems eventually emerge with the territory.
First, sufficient progress eventually breaks backwards compatibility. It’s a normal part of life, I suppose. The typical culprit is the realization that to make something run better you sometimes need to change the structure. I’ve gotten good about the habit of carefully thinking through the architecture on paper before I even open vim, but it still catches me now and then. Scientists need to know exactly how a result was produced, even after the “cleaner” version replaces the messy one that worked.
Second, complexity creeps in. You can use environments or containers, but things still drift, break (🐼), or become too heavy with boilerplate and barriers to creativity. Sometimes all you want is to test an idea without turning your project folder into a junk drawer of half-runs and slightly tweaked script copies, or having to set up virtual environments, Dockerfiles, or adapt to frameworks.
I’m not here to judge you. I’m here to help you.
So I made a small tool called mups that works with your prototyping style without moralizing you (it’s also my first time I publishing on PyPI)!
███╗ ███╗ ██╗ ██╗ ██████╗ ███████╗
████╗ ████║ ██║ ██║ ██╔══██╗ ██╔════╝
██╔████╔██║ ██║ ██║ ██████╔╝ ███████╗
██║╚██╔╝██║ ██║ ██║ ██╔═══╝ ╚════██║
██║ ╚═╝ ██║ ╚██████╔╝ ██║ ███████║
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝
[ Multi Use PipelineS ]
python -m pip install mups
python -m mups DIRPATH
One command “templates” your project folder by adding a few helper files, which I refer to as mupsification. After that, every time you launch the boot script, mups creates a fresh timestamped job directory that contains a snapshot of your code, your settings, the right environment (or a way to recreate it), and a README for future-you. You can even add custom settings to the config file and import them in your scripts. It can then run your script inside that isolated snapshot. Each job is self-contained, reproducible, and safe to archive, share, send to another machine, or throw at a cluster. No containers, no frameworks, no forcing you to reorganize your project.
Think of this as making IKEA-like blueprints of your code iterations.

You don’t even need mups after your script folder was mupsified. The generated files are already there and are all that’s needed.
mups sits in the gap between an idea and a commit
You want to change something? No problem. Edit your template folder, run the boot script, and a new job is created with all its dependencies. There are settings for inheritance too: sometimes you want the dependencies copied so a job is fully independent, and sometimes you want them linked to save space (handy when you’re running half a million jobs).
That’s it. You don’t have to import anything into your scripts—mups just adds a few extra files and no external dependencies. It embraces your chaos instead of lecturing you about structure.
Check out the project Gitlab and PyPI page for more details.
In a future update I’m planning to add the ability to not only select which scripts your job should copy through the config file but to copy specific functions. That way you don’t have to drag the entire kitchen sink when someone only needs a sponge.
Stay tuned for v0.1.0.
(…and bug fixes)