Skip to content

Commit

Permalink
[issue_415] Add support for python 3
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreiH committed Feb 22, 2019
1 parent a65a8af commit 9a534cc
Show file tree
Hide file tree
Showing 27 changed files with 183 additions and 120 deletions.
24 changes: 13 additions & 11 deletions .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
build: false

environment:
PYTHON: "C:\\Python27"
TOXENV: "py27"
matrix:
- PYTHON: "C:\\Python27"
PYTHON_VERSION: "2.7"
TOXENV: "py27"
- PYTHON: "C:\\Python36"
PYTHON_VERSION: "3.6"
TOXENV: "py36"

init:
- ECHO %PYTHON%
- ECHO %TOXENV%
- SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%
- ECHO %PYTHON%
- ECHO %TOXENV%
- SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%

install:
- python -m pip install --upgrade pip
# Latest tox 2.3.x is currently busted:
# https://bitbucket.org/hpk42/tox/issues/314/tox-command-busted-on-windows
- pip install tox==2.2.0

- python -m pip install --upgrade pip
- pip install tox==3.7.0

test_script:
- tox
- tox
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.idea/
.cache/
.tox/
*.egg-info
*.pyc
.coverage
build
dist
42 changes: 26 additions & 16 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,42 @@ language: python

matrix:
include:
- python: 2.7
- name: "Run test suite on Linux with python 2.7"
os: linux
python: 2.7
env: TOXENV=py27
- python: 2.7
- name: "Run test suite on Linux with python 3.6"
os: linux
python: 3.6
env: TOXENV=py36
- name: "Check code style with pylama on Linux with python 2.7"
os: linux
python: 2.7
env: TOXENV=pylama
- language: generic
os: osx
# 7.2 is OS X 10.11.x
- name: "Check code style with pylama on Linux with python 3.6"
os: linux
python: 3.6
env: TOXENV=pylama
# 10.1 is OS X 10.13.x
# https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions
osx_image: xcode7.2
- name: "Run test suite on OS X with python 2.7"
os: osx
osx_image: xcode10.1
language: generic
python: 2.7
env: TOXENV=py27
- name: "Run test suite on OS X with python 3.6"
language: generic
os: osx
env:
- TOXENV=py36
- HOMEBREW_NO_AUTO_UPDATE=1

install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
curl -O -s https://bootstrap.pypa.io/get-pip.py;
python get-pip.py --user;
export PATH=$PATH:~/Library/Python/2.7/bin;
pip install --user tox virtualenv;
else
pip install tox virtualenv;
fi

- ./.travis/install.sh

script:
- tox
- ./.travis/run.sh

notifications:
email:
Expand Down
30 changes: 30 additions & 0 deletions .travis/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

set -e
set -x

ci_requirements="pip setuptools tox virtualenv"

if [ "$TRAVIS_OS_NAME" == "osx" ]; then
if [[ ${TOXENV} == *"py27"* ]]; then
# install pip on the system python
curl -O https://bootstrap.pypa.io/get-pip.py
python get-pip.py --user
python -m pip install --user virtualenv
python -m virtualenv .venv/
elif [[ ${TOXENV} == *"py3"* ]]; then
# install current python3 with homebrew
# NOTE: the formula is now named just "python"
brew install python
command -v python3
python3 --version
python3 -m pip install virtualenv
python3 -m virtualenv .venv/
else
echo "unsupported $TOXENV: "${TOXENV}
exit 1
fi
source .venv/bin/activate
fi

python -m pip install $ci_requirements
10 changes: 10 additions & 0 deletions .travis/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

set -e
set -x

if [ "$TRAVIS_OS_NAME" == "osx" ]; then
source .venv/bin/activate
fi

tox
6 changes: 3 additions & 3 deletions mozdownload/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from __future__ import absolute_import, unicode_literals

import re
import urllib
from HTMLParser import HTMLParser

import requests
from six.moves.html_parser import HTMLParser
from six.moves.urllib.parse import unquote


class DirectoryParser(HTMLParser):
Expand Down Expand Up @@ -68,7 +68,7 @@ def handle_starttag(self, tag, attrs):
# Links look like: /pub/firefox/nightly/2015/
# We have to trim the fragment down to the last item. Also to ensure we
# always get it, we remove a possible final slash first
url = urllib.unquote(attr[1])
url = unquote(attr[1])
self.active_url = url.rstrip('/').split('/')[-1]

return
Expand Down
27 changes: 14 additions & 13 deletions mozdownload/scraper.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,21 @@
import os
import re
import sys
import urllib
from datetime import datetime
from urlparse import urlparse

import mozinfo
import progressbar as pb
import redo
import requests
from six.moves.urllib.parse import quote
from six.moves.urllib.parse import urlparse

from mozdownload import errors
from mozdownload import treeherder
from mozdownload.parser import DirectoryParser
from mozdownload.timezones import PacificTimezone
from mozdownload import treeherder
from mozdownload.utils import urljoin


APPLICATIONS = ('devedition', 'firefox', 'fennec', 'thunderbird')

# Some applications contain all locales in a single build
Expand Down Expand Up @@ -164,6 +163,7 @@ def _create_directory_parser(self, url):
@property
def binary(self):
"""Return the name of the build."""

def _get_binary():
# Retrieve all entries from the remote virtual folder
parser = self._create_directory_parser(self.path)
Expand Down Expand Up @@ -195,8 +195,8 @@ def binary_regex(self):
@property
def url(self):
"""Return the URL of the build."""
return urllib.quote(urljoin(self.path, self.binary),
safe='%/:=&?~#+!$,;\'@()*[]|')
return quote(urljoin(self.path, self.binary),
safe='%/:=&?~#+!$,;\'@()*[]|')

@property
def path(self):
Expand Down Expand Up @@ -248,6 +248,7 @@ def detect_platform(self):

def download(self):
"""Download the specified file."""

def total_seconds(td):
# Keep backward compatibility with Python 2.6 which doesn't have
# this method
Expand Down Expand Up @@ -417,7 +418,7 @@ def get_latest_build_date(self):
parser.entries = parser.filter(r'.*%s\.txt' % self.platform_regex)
if not parser.entries:
message = 'Status file for %s build cannot be found' % \
self.platform_regex
self.platform_regex
raise errors.NotFoundError(message, url)

# Read status file for the platform, retrieve build id,
Expand Down Expand Up @@ -467,13 +468,13 @@ def get_build_info_for_date(self, date, build_index=None):
# ensure to select the correct subfolder for localized builds
'L10N': '(-l10n)?' if self.locale_build else '',
'PLATFORM': '' if self.application not in (
'fennec') else '-' + self.platform
'fennec') else '-' + self.platform
}

parser.entries = parser.filter(regex)
parser.entries = parser.filter(self.is_build_dir)

if has_time:
if date.strftime('%H-%M-%S') != '00-00-00':
# If a time is included in the date, use it to determine the
# build's index
regex = r'.*%s.*' % date.strftime('%H-%M-%S')
Expand All @@ -482,7 +483,7 @@ def get_build_info_for_date(self, date, build_index=None):
if not parser.entries:
date_format = '%Y-%m-%d-%H-%M-%S' if has_time else '%Y-%m-%d'
message = 'Folder for builds on %s has not been found' % \
self.date.strftime(date_format)
self.date.strftime(date_format)
raise errors.NotFoundError(message, url)

# If no index has been given, set it to the last build of the day.
Expand Down Expand Up @@ -690,7 +691,7 @@ def get_build_info(self):
parser = self._create_directory_parser(url)
if not parser.entries:
message = 'Folder for specific candidate builds at %s has not' \
'been found' % url
'been found' % url
raise errors.NotFoundError(message, url)

self.show_matching_builds(parser.entries)
Expand Down Expand Up @@ -909,11 +910,11 @@ def get_build_info_for_index(self, build_index=None):
# If a timestamp is given, retrieve the folder with the timestamp
# as name
parser.entries = self.timestamp in parser.entries and \
[self.timestamp]
[self.timestamp]

elif self.date:
# If date is given, retrieve the subset of builds on that date
parser.entries = filter(self.date_matches, parser.entries)
parser.entries = list(filter(self.date_matches, parser.entries))

if not parser.entries:
message = 'No builds have been found'
Expand Down
6 changes: 3 additions & 3 deletions mozdownload/treeherder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
from __future__ import absolute_import, unicode_literals

import logging
import six

from thclient import TreeherderClient

from mozdownload.errors import NotSupportedError


PLATFORM_MAP = {
'android-api-9': {'build_platform': 'android-2-3-armv7-api9'},
'android-api-11': {'build_platform': 'android-4-0-armv7-api11'},
Expand Down Expand Up @@ -69,11 +69,11 @@ def query_builds_by_revision(self, revision, job_type_name='Build', debug_build=

try:
self.logger.info('Querying {url} for list of builds for revision: {revision}'.format(
url=self.client.server_url, revision=revision))
url=self.client.server_url, revision=revision))

# Retrieve the option hash to filter for type of build (opt, and debug for now)
option_hash = None
for key, values in self.client.get_option_collection_hash().iteritems():
for key, values in six.iteritems(self.client.get_option_collection_hash()):
for value in values:
if value['name'] == ('debug' if debug_build else 'opt'):
option_hash = key
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mozinfo >= 0.9
mozinfo >= 1.0.0
progressbar2 >= 3.34.3
redo==2.0.2
requests >= 2.9.1, <3.0.0
treeherder-client >= 4.0.0, <5.0.0
requests >= 2.21.0, <3.0.0
treeherder-client >= 5.0.0, <6.0.0
2 changes: 1 addition & 1 deletion tests/cli/test_cli_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ def test_unrecognized_argument(self):
except subprocess.CalledProcessError as e:
output = e.output

self.assertRegexpMatches(output, r'mozdownload: error: unrecognized arguments: --abc')
self.assertRegexpMatches(output, r'mozdownload: error: unrecognized arguments: --abc'.encode('utf-8'))
2 changes: 1 addition & 1 deletion tests/cli/test_cli_print_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ def test_print_url_argument(self):
except subprocess.CalledProcessError as e:
output = e.output

self.assertRegexpMatches(output, url)
self.assertRegexpMatches(output, url.encode('utf-8'))
6 changes: 3 additions & 3 deletions tests/cli/test_correct_scraper.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
# You can obtain one at http://mozilla.org/MPL/2.0/.

import os
import six

import mozfile
import mozhttpd_base_test as mhttpd
from mock import patch

from mozdownload import cli
import mozhttpd_base_test as mhttpd


tests = {
'release': {
Expand Down Expand Up @@ -47,7 +47,7 @@ class TestCLICorrectScraper(mhttpd.MozHttpdBaseTest):

@patch('mozdownload.treeherder.Treeherder.query_builds_by_revision')
def test_cli_scraper(self, query_builds_by_revision):
for scraper_type, data in tests.iteritems():
for scraper_type, data in six.iteritems(tests):
if data.get('builds'):
query_builds_by_revision.return_value = data['builds']

Expand Down
8 changes: 7 additions & 1 deletion tests/cli/test_output.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#!/usr/bin/env python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

import subprocess
import unittest

Expand All @@ -10,4 +16,4 @@ class TestCLIOutput(unittest.TestCase):
def test_cli_executes(self):
"""Test that cli will start and print usage message"""
output = subprocess.check_output(['mozdownload', '--help'])
self.assertTrue(cli.__doc__.format(__version__) in output)
self.assertTrue(cli.__doc__.format(__version__) in output.decode("utf-8"))
Loading

0 comments on commit 9a534cc

Please sign in to comment.