Testing Mac OS X with specific Python version in Travis CI

How to test Python executable file with specific version in Mac OS X?

  • Travis CI basic options
  • MacPorts
  • Python, pip and PyInstaller

Travis CI basic options

Test with Ubuntu and Mac OS X platform.

Because of Travis CI are not provide Python language in "osx" platform, so we choose "generic".

With "matrix" option, the Linux and OS X platform can test at same time.

In OS X platform, set a "PYTHON" environment variable to represent specific version of Python.

# .travis.yml

language: python

matrix:
  include:

    - os: linux
      sudo: required
      python: 3.6
      dist: xenial

    - os: linux
      sudo: required
      python: 3.7
      dist: xenial

    - os: osx
      osx_image: xcode10
      language: generic
      env: PYTHON=36

Then, use "addons" option to install packages in Ubuntu platform with "apt" option.

For example, install SWIG.

addons:
  apt:
    packages:
      - swig

MacPorts

Since Homebrew always provide newest version of Python, it is recommended to use MacPorts as package management tool.

With "TRAVIS_OS_NAME" variable, the bash command will only execute in OS X platform.

Homebrew is already installed by Travis CI, so you can install dependency directly.

Download MacPort from https://raw.githubusercontent.com/GiovanniBussi/macports-ci/master/macports-ci and install it.

# For OSX
before_install:

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    brew install swig;
    curl -LO https://raw.githubusercontent.com/GiovanniBussi/macports-ci/master/macports-ci;
    source ./macports-ci install;
    fi

Python, pip and PyInstaller

Install Python and pip by MacPorts.

Type "yes" front of command can be pass the ask of MacPorts during installation.

And using port select command to update python3 and pip soft link in /usr/local/bin.

PyInstaller can be installed by pip, but should install with "--user" flag.

That's because of MacPorts will install executable scripts to /opt/local, which is protected by system, it cannot be done with "sudo".

The user folder /Users/travis/Library/Python/x.y/bin (where "x.y" is the Python version) is not in "PATH" variable, so add it using $(python3 -c "import site; print(site.USER_BASE)")/bin after installation completed.

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    yes | sudo port install python$PYTHON;
    yes | sudo port install py$PYTHON-pip;
    sudo port select --set python3 python$PYTHON;
    sudo port select --set pip pip$PYTHON;
    pip install pyinstaller --user;
    export PATH=$PATH:$(python3 -c "import site; print(site.USER_BASE)")/bin;
    fi

Check the versions.

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    python3 --version;
    pip --version;
    pyinstaller --version;
    fi

Install Python modules from requirements.txt. This step is also recommand using "--user" flag without "sudo".

This step will automatically executed in Linux platform.

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    pip install -r requirements.txt --user;
    fi

Summary

The final version of configuration file looks like this:

# Travis-Ci for Pyslvs-PyQt5
language: python

matrix:
  include:

    - os: linux
      sudo: required
      python: 3.6
      dist: xenial

    - os: linux
      sudo: required
      python: 3.7
      dist: xenial

    - os: osx
      osx_image: xcode10
      language: generic
      env: PYTHON=36

branches:
  only:
    - master
    - /^dev\d*[.]?\d*$/

addons:
  apt:
    packages:
      - swig

# For OS X
before_install:

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    brew install swig;
    curl -LO https://raw.githubusercontent.com/GiovanniBussi/macports-ci/master/macports-ci;
    source ./macports-ci install;
    fi

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    yes | sudo port install python$PYTHON;
    yes | sudo port install py$PYTHON-pip;
    sudo port select --set python3 python$PYTHON;
    sudo port select --set pip pip$PYTHON;
    pip install pyinstaller --user;
    export PATH=$PATH:/Users/travis/Library/Python/$PYTHON/bin;
    fi

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    python3 --version;
    pip --version;
    pyinstaller --version;
    fi

  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
    pip install -r requirements.txt --user;
    fi

script:
  - make

before_cache:
  - rm -rf $HOME/.cache/pip/log

cache:
  directories:
    - $HOME/.cache/pip