Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

Python Package Versioning Best Practices

If you add new features or add a breaking change, you want to change the version of your package. In this lesson you’ll meet semantic versioning and how you can use it in your project.

Note: If you want to learn more about semantic versioning, make sure to check out semver.org.

00:00 Versioning is critical for letting users know the compatibility of a piece of software. You may be most familiar with certain versions of software having security vulnerabilities, or features missing in newer or older versions.

00:14 The most frustrating can occur when a new version of software breaks your project, so it’s definitely an important concept to understand when working with external pieces of code or giving your code to others.

00:24 PyPI requires a version when you upload a package, so that users know when the code changes. If you update your package and attempt to re-upload it, PyPI will require a new version number before it accepts it.

00:36 While there are many different methods for controlling version number, a common default is semantic versioning. This keeps your version in three components, each meaning something different.

00:46 Let’s head to setup.py and take a look. Here you can see your version is broken up into three segments. This first number is incremented when you make a major change.

00:58 Major changes can break code, where the API of your software is now different.

01:04 If you use a piece of software that’s 1.x.x and it’s updated to 2.x.x, there’s a good chance you’re going to have to do some work before you can make your software compatible with it. The second number is incremented when minor changes are made.

01:19 A minor change may be included functionality or new features, but it should remain backwards-compatible. Finally, the third number is incremented when patches are added.

01:30 Patches are generally bug fixes or closing up security vulnerabilities. Like minor changes, they should also be backwards-compatible. For this project, version is listed in two different places. You can see it in setup.py here, and you can also see it in __init__.py.

01:47 Now, I’m an expert at forgetting to update something when it’s located in multiple places, so fortunately there’s a tool available called Bumpversion. Open up your terminal and do pip install bumpversion.

02:05 Bumpversion is a great tool to keep your version numbers consistent. Let’s say we wanted to add a minor change to our codebase. You could just go ahead and type in bumpversion,

02:20 you should define what the --current-version is, which right now it’s 1.0.0,

02:26 make a minor update,

02:30 and it’s located in setup.py, and in reader/__init__.py. Now when you run this—

02:41 oh, let’s see what’s going on here, No file or directory.

02:46 And it’s because I’m not in the correct directory, so let’s just change directory into the actual project folder and run the same command. Cool! No errors, and you can see your version here is "1.1.0".

03:01 And if you go to setup.py, it’s also "1.1.0". Now, if you look at the line that you had to type out to do that, it was quite a bit in there.

03:10 Bumpversion has a feature where you can set up a Bumpversion config file that will keep track of everything for you. If you’re interested, head to their documentation and take a look at how to set one up.

03:23 Once you have the config file, all you would have to do is call something like bumpversion major or bumpversion minor, and it would do all of your updates for you. For larger projects, this is a great tool to use. Okay, now that you’ve got a handle on versioning, the last thing you need to learn is how to include other types of files into your package before you can build them.

03:46 We’ll talk about that in the next video. See you there.

Ifeanyi A on Nov. 2, 2022

For bumpversion

I got errors while running the bumpversion command in the terminal. I’m sure I am in the right directory. It gave errors pointing to my ubuntu system files.

Errors:
Traceback (most recent call last):
File "/home/d1amz/.local/bin/bumpversion", line 8, in <module>
sys.exit(main())
File "/home/d1amz/.local/lib/python3.6/site-packages/bumpversion
/cli.py", line 124, in main
_check_files_contain_version(files, current_version, context)
 File "/home/d1amz/.local/lib/python3.6/site-packages/bumpversion
/cli.py", line 618, in _check_files_contain_version
f.should_contain_version(current_version, context)
File "/home/d1amz/.local/lib/python3.6/site-packages/bumpversion
/utils.py", line 51, in should_contain_version
if self.contains(search_expression):
File "/home/d1amz/.local/lib/python3.6/site-packages/bumpversion
/utils.py", line 78, in contains
with open(self.path, "rt", encoding="utf-8") as f:
FileNotFoundError: [Errno 2] No such file or directory: '1.0.0'
For python -m flag on reader

I couldn’t also run the ‘python - reader’ command. It gave other errors pointing to my system files.

Errors:
Traceback (most recent call last):
File "/usr/lib/python3.6/runpy.py", line 193, in 
_run_module_as_main
"__main__", mod_spec)
 File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
 File "/home/d1amz/.local/lib/python3.6/site-packages/reader
/__main__.py", line 13, in <module>
from reader._cli import cli
 File "/home/d1amz/.local/lib/python3.6/site-packages/reader
/_cli.py", line 210, in <module>
@click.pass_obj
File "/usr/lib/python3/dist-packages/click/decorators.py", line 
170, in decorator
_param_memo(f, OptionClass(param_decls, **attrs))
File "/usr/lib/python3/dist-packages/click/core.py", line 1460, in 
__init__
Parameter.__init__(self, param_decls, type=type, **attrs)
TypeError: __init__() got an unexpected keyword argument 'hidden'

I’m running on python 3.6 so not sure if that’s the problem or perhaps bumpversion is outdated.

Become a Member to join the conversation.