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.

How Tests Can Help You Migrate Your Code Between Different Python Versions

After meeting some of the main differences between Python 2 and 3, this lesson shows you how tests can help you migrating your Python code to another version. In this case a feature of the datetime module introduced in Python 2.7 is tested and backported to Python 2.6.

00:00 So, let’s go back to Travis and see what the issues are that we’re seeing when building against Python 3.2 and 2.6. We’ll first take a look at 2.6 and see what could be the problem.

00:12 This shows us the build output from Travis while building and testing our delorean package. As you can see, it installs fine without much issue. The tests run and we have one exception.

00:23 It says that the 'datetime.timedelta' object has no attribute 'total_seconds'. That is interesting. This likely means that .total_seconds() was introduced in Python 2.7 and is not available in Python 2.6.

00:38 We can easily solve the issue here, and let’s take a look at it real fast in the source code. So, let’s open up that particular test.

00:50 Let’s see here. It was epoch test that was failing, and it’s simply saying to get the epoch time and assert that. So the method we want to look at is the .epoch() in the dates module.

01:03 Excellent. So, this is the portion of the test that is failing, and this apparently isn’t available in Python 2.6. So, we can easily fix this issue, and I believe this is the only place that we use .total_seconds(). Let’s just take a look here.

01:20 Yeah, this is the only place. So we can easily rework this to make it compatible with 2.6. So all we need to do is write a function to get total seconds that takes a timedelta and returns

01:35 the number of seconds that it represents. Let’s just quickly just write out a docstring for this, so we know in the future what it does. I tend to forget what methods I wrote yesterday do. So let’s just simply say 'This method takes a timedelta' 'and returns the number of seconds it represents with the resolution of 10 ** 6'.

02:14 Awesome. So let’s return. Now, we all know that—or hopefully we all know—that timedelta has a .seconds, .milliseconds, and .days attributes, which they use to represent the time difference between two datetimes.

02:29 So, in order to get the total number of seconds, we have to add those all up together. Let’s first deal with microsecond, so td.microseconds plus we then have

02:48 td.seconds plus td.days times 24 hours in a day, and 3600 seconds in an hour,

03:04 then multiplied by 1e6, then divided again by 1e6. And that should provide us with the same functionality that the .total_seconds() did. So we’ll simply rewrite this so that it takes the delta as an argument, get_total_second(), and then we’ll pass delta in.

03:32 Beautiful. Let’s make sure that actually works. Let’s run our tests here,

03:39 make test.

03:43 We have an issue here, has no attribute 'day'. Let’s go back here, I must have miswrote something here. .days is what we actually want. Let’s re-run the test again. Yay.

03:53 Everything works, this is awesome. So, when converting an application from any version of Python or anytime you’re changing code and you have tests, you should rewrite the thing that you’re trying to mimic or improve, and then run the tests to verify that none of the functionality has changed.

04:13 So, before we had a test for test_epoch(), it would return the correct number of total seconds since January of 1970. We then realized that this wouldn’t work in Python 2.6.

04:24 We wrote a workaround. We used that same test that we had in the previous version to verify that we did not break any of the current functionality in the library.

04:34 This helps with dealing with regressions so you don’t fix something and then break something else. I’m going to run this through Travis and when we’re back I’ll show you how everything worked, and then we’ll move on to fixing Python 3.2.

Become a Member to join the conversation.