Skip to content



This file describes how to

  • contribute changes to the project, and
  • upload released to the PyPI repository.

Most of the management commands have been directly placed inside the Makefile:

make [<alias>]  # on UNIX-like environments
python make [<alias>]  # if make is unavailable

The latter depends on py-make>=0.1.0.

Use the alias help (or leave blank) to list all available aliases.


Contributions to the project are made using the "Fork & Pull" model. The typical steps would be:

  1. create an account on github
  2. fork tqdm
  3. make a local clone: git clone
  4. make changes on the local copy
  5. test (see below) and commit changes git commit -a -m "my message"
  6. push to your GitHub account: git push origin
  7. create a Pull Request (PR) from your GitHub fork (go to your fork's webpage and click on "Pull Request." You can then add a message to describe your proposal.)


Don't worry too much - maintainers can help reorganise contributions. However it would be helpful to bear in mind:

  • The standard core of tqdm, i.e. tqdm.std.tqdm
    • must have no dependencies apart from pure python built-in standard libraries
    • must have negligible impact on performance
    • should have 100% coverage by unit tests
    • should be appropriately commented
    • should have well-formatted docstrings for functions
      • under 76 chars (incl. initial spaces) to avoid linebreaks in terminal pagers
      • use two spaces between variable name and colon, specify a type, and most likely state that it's optional: VAR<space><space>:<space>TYPE[, optional]
      • use [default: ...] for default values of keyword arguments
    • will not break backward compatibility unless there is a very good reason
      • e.g. breaking py26 compatibility purely in favour of readability (such as converting dict(a=1) to {'a': 1}) is not a good enough reason
    • API changes should be discussed carefully
    • remember, with millions of downloads per month, tqdm must be extremely fast and reliable
  • Any other kind of change may be included in a (possibly new) submodule
    • submodules are likely single python files under the main tqdm/ directory
    • submodules extending tqdm.std.tqdm or any other module (e.g. tqdm.notebook.tqdm, tqdm.gui.tqdm)
    • CLI wrapper tqdm.cli
      • if a newly added tqdm.std.tqdm option is not supported by the CLI, append to tqdm.cli.UNSUPPORTED_OPTS
    • can implement anything from experimental new features to support for third-party libraries such as pandas, numpy, etc.
    • submodule maturity
      • alpha: experimental; missing unit tests, comments, and/or feedback; raises tqdm.TqdmExperimentalWarning
      • beta: well-used; commented, perhaps still missing tests
      • stable: >10 users; commented, 80% coverage
  • .meta/
    • A "hidden" folder containing helper utilities not strictly part of the tqdm distribution itself


Once again, don't worry too much - tests are automated online, and maintainers can also help.

To test functionality (such as before submitting a Pull Request), there are a number of unit tests.

Standard unit tests#

The standard way to run the tests:

  • install tox
  • cd to the root of the tqdm directory (in the same folder as this file)
  • run the following command:
[python] make test
# or:
tox --skip-missing-interpreters

This will build the module and run the tests in a virtual environment. Errors and coverage rates will be output to the console/log. (Ignore missing interpreters errors - these are due to the local machine missing certain versions of Python.)

Note: to install all versions of the Python interpreter that are specified in tox.ini, you can use MiniConda to install a minimal setup. You must also make sure that each distribution has an alias to call the Python interpreter: python27 for Python 2.7's interpreter, python32 for Python 3.2's, etc.

Alternative unit tests with pytest#

Alternatively, use pytest to run the tests just for the current Python version:

  • install test requirements: [python] make install_test
  • run the following command:
[python] make alltests


This section is intended for the project's maintainers and describes how to build and upload a new release. Once again, [python] make [<alias>] will help. Also consider pip installing development utilities: [python] make install_build at a minimum, or a more thorough conda env create.

Pre-commit Hook#

It's probably a good idea to use the pre-commit (pip install pre-commit) helper.

Run pre-commit install for convenient local sanity-checking.

Semantic Versioning#

The tqdm repository managers should:


To check that the file is compliant with PyPI requirements (e.g. version number; reStructuredText in README.rst) use:

[python] make testsetup

To upload just metadata (including overwriting mistakenly uploaded metadata) to PyPI, use:

[python] make pypimeta

Merging Pull Requests#

This section describes how to cleanly merge PRs.

1 Rebase#

From your project repository, merge and test (replace pr-branch-name as appropriate):

git fetch origin
git checkout -b pr-branch-name origin/pr-branch-name
git rebase master

If there are conflicts:

git mergetool
git rebase --continue

2 Push#

Update branch with the rebased history:

git push origin pr-branch-name --force

Non maintainers can stop here.

Note: NEVER just git push --force (this will push all local branches, overwriting remotes).

3 Merge#

git checkout master
git merge --no-ff pr-branch-name

4 Test#

[python] make alltests

5 Push to master#

git push origin master

Building a Release and Uploading to PyPI#

Formally publishing requires additional steps: testing and tagging.


Ensure that all online CI tests have passed.


  • ensure the version has been tagged. The tag format is v{major}.{minor}.{patch}, for example: v4.4.1. The current commit's tag is used in the version checking process. If the current commit is not tagged appropriately, the version will display as v{major}.{minor}.{patch}.dev{N}+g{commit_hash}.


GitHub Actions (GHA) CI should automatically do this after pushing tags. Manual instructions are given below in case of failure.

Build tqdm into a distributable python package:

[python] make build

This will generate several builds in the dist/ folder. On non-windows machines the windows exe installer may fail to build. This is normal.

Finally, upload everything to PyPI. This can be done easily using the twine module:

[python] make pypi

Also, the new release can (should) be added to GitHub by creating a new release from the web interface; uploading packages from the dist/ folder created by [python] make build. The wiki can be automatically updated with GitHub release notes by running make within the wiki repository.

Docker images may be uploaded to Assuming docker is installed:

make -B docker
docker login
docker push tqdm/tqdm:latest
docker push tqdm/tqdm:$(docker run -i --rm tqdm/tqdm -v)

Snaps may be uploaded to Assuming snapcraft is installed (snap install snapcraft --classic --beta):

make snap
snapcraft login
snapcraft push tqdm*.snap --release stable


  • you can also test on the PyPI test servers before the real deployment
  • in case of a mistake, you can delete an uploaded release on PyPI, but you cannot re-upload another with the same version number
  • in case of a mistake in the metadata on PyPI (e.g. bad README), updating just the metadata is possible: [python] make pypimeta

Updating Websites#

The most important file is .readme.rst, which should always be kept up-to-date and in sync with the in-line source documentation. This will affect all of the following:

  • README.rst (generated by during make build)
  • The main repository site which automatically serves the latest README.rst as well as links to all of GitHub's features. This is the preferred online referral link for tqdm.
  • The PyPI mirror which automatically serves the latest release built from README.rst as well as links to past releases.
  • Many external web crawlers.

Additionally (less maintained), there exists:

Helper Bots#

There are some helpers in .github/workflows to assist with maintenance.

  • Comment Bot
    • allows maintainers to write /tag vM.m.p commit_hash in an issue/PR to create a tag
  • Post Release
  • Benchmark


For experienced devs, once happy with local master, follow the steps below. Much is automated so really it's steps 1-5, then 11(a).

  1. test ([python] make alltests or rely on pre-commit)
  2. git commit [--amend] # -m "bump version"
  3. git push
  4. wait for tests to pass a) in case of failure, fix and go back to (1)
  5. git tag vM.m.p && git push --tags or comment /tag vM.m.p commit_hash
  6. [AUTO:GHA] [python] make distclean
  7. [AUTO:GHA] [python] make build
  8. [AUTO:GHA] upload to PyPI. either: a) [python] make pypi, or b) twine upload -s -i $(git config user.signingkey) dist/tqdm-*
  9. [AUTO:GHA] upload to docker hub: a) make -B docker b) docker push tqdm/tqdm:latest c) docker push tqdm/tqdm:$(docker run -i --rm tqdm/tqdm -v)
  10. [AUTO:GHA] upload to snapcraft: a) make snap, and b) snapcraft push tqdm*.snap --release stable
  11. Wait for GHA to draft a new release on a) replace the commit history with helpful release notes, and click publish b) [AUTO:GHA] attach dist/tqdm-* binaries (usually only *.whl*)
  12. [SUB][AUTO:GHA-rel] run make in the wiki submodule to update release notes
  13. [SUB][AUTO:GHA-rel] run make deploy in the docs submodule to update website
  14. [SUB][AUTO:GHA-rel] accept the automated PR in the feedstock submodule to update conda
  15. [AUTO:GHA-rel] update the gh-pages project benchmarks a) [python] make testasvfull b) asv gh-pages


  • [AUTO:GHA]: GitHub Actions CI should automatically do this after git push --tags (5)
  • [AUTO:GHA-rel]: GitHub Actions CI should automatically do this after release (11a)
  • [SUB]: Requires one-time make submodules to clone docs, wiki, and feedstock