Package: barrel
BarrelPython command line tools that are easy to install, repo-isolated, and update themselves.Users install your package with:$curl-sSLhttps://barrel.dev/install.py|python3-<pypi_package_name>And update it with:$<cli_name>updateOverviewWhat Barrel isHow Barrel worksBarrel for package authorsWhat Barrel doesn't doAlternativesOverviewPython can be a great language for writing command line tools,
but your users shouldn't have to be Python experts to use them.For tools that aregloballyinstalled,
people tend to do things likepip install --user <package>,write a custom installation script,
or install and use a wrapper likepipx.This works when you intend to use the same version of the CLI no matter what you're working on.
But there are other things like static site generators and automation tools that should be installed specifically into a user'srepository.
The version installed needs to be isolated and pinned,
so you can use the same tools on multiple repos/projects without worrying about update conflicts and forcing them all to use the same version.There are obviously ways to deal with this today (seealternatives),
but they all require a certain amount of Python-ecosystem knowledge that your users may not have.
Especially if your CLI is written in Python,
but the user doesn't actually use Python when interacting with it.What Barrel isBarrel is an installation script,
embeddable package,
and set of conventions for installing an isolated and versioned command line tool into a repo.
As a bonus, Barrel makes it easy for you to have a self-updating CLI.The goal is tosimplifythe process (especially for non-Pythonistas) and provide a developer experience that doesn't suck.
It does this by being a lightweight wrapper around standard, known conventions that can be used as a "one-liner".Using well-known conventions likerequirements.txtalso allows standard CI/CD workflows and other services/tools to "just work",
without knowing or caring about Barrel itself.
This makes it automatically compatible with hosting services like Netlify,
and dependency management automation like Dependabot.How Barrel worksThe initial install of a command line tools is done with a script.
A curl -> Python command is the easiest way to do this,
and doesn't requireanyadditional dependencies besides Python 3 (which your CLI requires anyway).$curl-sSLhttps://barrel.dev/install.py|python3-<pypi_package_name>This will create a virtual environment at.venvandrequirements.txtfile.
The.venvshould be in.gitignorebut therequirements.txtshould be committed.
The install script will help point out these details for people that aren't familiar with them.Therequirements.txtfile will look something like this and effectively"pins"the version in use until an update is made:# This file is managed automatically by <package>
<package>==2.3.0Once installed, updates can be done two ways.Barrel is integrated into the package/CLI itself, providing a command like<package> update.
This is the most user-friendly way to do it,
since they already have your CLI installed and don't have to remember or save the curl command.But if you don't include Barrel in your package,
you can always run the curl command again to update the package (using the--reinstalloption).The only caveat at this point is that.venv/bin/needs to be in the user'sPATH,
or they need to use./.venv/bin/<package>directly.
The install script will help point this out and how it can be done (ex.export PATH="./.venv/bin:$PATH").Barrel for package authorsTo use Barrel for the installation process,
you just need a published package that is your CLI.You can copyinstall.pyto your own repo or site,
but the we always keep an up-to-date hosted version athttps://barrel.dev/install.py.Your documentation should tell users how to use the curl command (including your package name as the argument).$curl-sSLhttps://barrel.dev/install.py|python3-<pypi_package_name>Youshouldadd "barrel" as a dependency in your package and provide a self-updating experience.
To do this, you just need to call theupdatefunction with the name of your package.
You can add it to your CLI like this example usingclick:importbarrel@click.command()defupdate():"""Update your version of combine"""barrel.update("combine")If you don't add "barrel" as a dependency,
then you'll need to tell users to run the curl command again to update with the--reinstalloption.$curl-sSLhttps://barrel.dev/install.py|python3-<pypi_package_name>--reinstallThings to know:Barrel supports Python 3 onlyBarrel expects your package to be the only direct dependency the user needs to install (i.e. theirrequirements.txtwill only end up with your package in it --nothing else)Barrel expects your package to have an entrypoint (by default this should be the same as the package name)What Barrel doesn't doThe primary goal of Barrel is tosimplifythe dependency installation/update process for people.
So it shouldn't come as a surprise that certain features you know from full-fledged dependency managers are intentionally missing.Freezealldependency requirementsTherequirements.txtwon't include all of the pinned versions of indirect/transitive dependencies.
While that would help with the predictability of an install,
those details don't (and arguablyshouldn't) matter to most people and can cause a lot of noise in automated dependency update tools.If you're authoring a package that uses Barrel,
you should take extra care to specify the ranges of your dependencies that you knowwork,
and put a CI process in place to regularly test a fresh install just like your users would get.Lock to a specific Python versionBarrel won't save the Python version it used during the install,
and it won't force everyone on the repo to use the same Python version.Managing multiple Python versions is not for everyone.
There are tools and ways to do it,
but it can get complicated fast.Barrel only works with Python 3 sincePython 2 was sunset in 2020.
This makes it easier.Similar to the point on frozen requirements,
it should be the package authors responsiblity to define the range of Python3 versions you support and to make sure they work.Use a matrix in your CI tests to stay on top of it.Alternativespip by itselfBarrel is a wrapper around standard pip processes and conventions,
so you can obviously do the same thing with pip directly.
The problem is, there are a series of steps that people either have to already know or have scripted.
There are a lot of decisions to make along the way and you can easily lose people just by having an overly complicated install process for someone who isn't familiar with Python.Barrel essentially does these steps for a new install:$python3-mvenv.venv$./.venv/bin/pipinstall<package>$./.venv/bin/pipfreeze|grep<package>>requirements.txtThese steps for a fresh install of an existing repo:$python3-mvenv.venv$./.venv/bin/pipinstall-rrequirements.txtAnd these steps for update:$./.venv/bin/pipinstall-U<package>$./.venv/bin/pipfreeze|grep<package>>requirements.txtBarrel makes the install step (new or existing) a curl one-liner,
and the update step as simple as<package> update.pipxOn the surface,pipxis pretty similar in goals.
The difference is that pipx is aimed at tools that are installedgloballyon a user's machine.
This is not exactly what you want if your package needs to be versioned to a specific user's repo.If you try to use a globally installed command across multiple repos,
you run into problems when a new version of the command is released and new features are added/removed that aren't compatible withallof your repos (build command changed syntax, YAML config settings changed, etc.).
The only solution you have is to update all of them at once,
which can be a pretty unpleasant experience depending on the changes required.poetry, pipenv, etc.In a lot of ways, Barrel is intended to be a simpler alternative to these.
BothPoetryandPipenvcan be used for installing a specific version of a Python package into a repo.
But they come with a lot of other baggage that you simply don't need for a single-dependency repo.Both require you to install the tool itself first (which is a process of its own),
and can force other decisions like locking to a specific Python version,
new commands to learn,
and extra headaches if poetry/pipenv themselves break!
Which does happen (surprisinglyg frequently in the case of Pipenv) and can require a lot of difficult troubleshooting.
Barrel largely avoids this by doing basicpipcommands andrequirements.txtflows that are unlikely to have any problems.