Add ProjectTestingInterface to horizon.
Horizon is the last project that doesn't have support for the common Project Testing Interface. This gets horizon up to speed with the other bits, but shouldn't break any of the existing interfaces. Change-Id: I464c3b10d9708a0b7b5ffd42c88cd3cf515ef6a7
This commit is contained in:
parent
4f7ee81b58
commit
c93e7c06fd
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,6 +5,7 @@
|
||||
.coverage*
|
||||
.noseids
|
||||
coverage.xml
|
||||
nosetests.xml
|
||||
pep8.txt
|
||||
pylint.txt
|
||||
reports
|
||||
@ -13,5 +14,8 @@ openstack_dashboard/local/local_settings.py
|
||||
docs/build/
|
||||
docs/source/sourcecode
|
||||
.venv
|
||||
.tox
|
||||
build
|
||||
dist
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
|
57
AUTHORS
57
AUTHORS
@ -1,57 +0,0 @@
|
||||
Alessio Ababilov <aababilov@griddynamics.com>
|
||||
Andrews Medina <andrewsmedina@gmail.com>
|
||||
Andy Chong <andycjw@gmail.com>
|
||||
Anthony Young <sleepsonthefloor@gmail.com>
|
||||
Arvind Somya <asomya@cisco.com>
|
||||
Bernhard M. Wiedemann <bwiedemann@suse.de>
|
||||
Carlo Truijllo <truijllo@crs4.it>
|
||||
Chuck Short <chuck.short@canonical.com>
|
||||
Cole Robinson <crobinso@redhat.com>
|
||||
Dean Troyer <dtroyer@gmail.com>
|
||||
Devin Carlen <devin.carlen@gmail.com>
|
||||
Doug Doan <dougdoan@gmail.com>
|
||||
Duncan McGreggor <duncan@dreamhost.com>
|
||||
Emma Steimann <emmasteimann@gmail.com>
|
||||
Erwan Gallen <dev@zinux.com>
|
||||
Ewan Mellor <ewan.mellor@citrix.com>
|
||||
Gabriel Hurley <gabriel@strikeawe.com>
|
||||
Ghe Rivero <ghe@debian.org>
|
||||
Greg Althaus <galthaus@austin.rr.com>
|
||||
Hengqing Hu <hudayou@hotmail.com>
|
||||
Ionuț Arțăriși <iartarisi@suse.cz>
|
||||
Ivan Kolodyazhny <e0ne@e0ne.info>
|
||||
J. Daniel Schmidt <jdsn@suse.de>
|
||||
Jake Dahn <jake@ansolabs.com>
|
||||
Jake Zukowski <jake@ponyloaf.com>
|
||||
James E. Blair <jeblair@hp.com>
|
||||
Jay Pipes <jaypipes@gmail.com>
|
||||
Jeffrey Wilcox <jeffjapan@gmail.com>
|
||||
Jesse Andrews <anotherjesse@gmail.com>
|
||||
Jim Yeh <lemonlatte@gmail.com>
|
||||
John Postlethwait <john.postlethwait@nebula.com>
|
||||
Joseph Heck <heckj@mac.com>
|
||||
Joshua McKenty <joshua@pistoncloud.com>
|
||||
Julien Danjou <julien.danjou@enovance.com>
|
||||
Ke Wu <ke.wu@ibeca.me>
|
||||
Ken Pepple <ken.pepple@gmail.com>
|
||||
Mark Gius <launchpad@markgius.com>
|
||||
Michael Szilagyi <mszilagyi@gmail.com>
|
||||
Mike Perez <thingee@gmail.com>
|
||||
Mike Scherbakov <mihgen@gmail.com>
|
||||
Monty Taylor <mordred@inaugust.com>
|
||||
Neil Johnston <onewheeldrive.net@gmail.com>
|
||||
Paul McMillan <paul.mcmillan@nebula.com>
|
||||
Sam Morrison <sorrison@gmail.com>
|
||||
Stephane Angot <sa@hydre.org>
|
||||
termie <github@anarkystic.com>
|
||||
Thierry Carrez <thierry@openstack.org>
|
||||
Tihomir Trifonov <t.trifonov@gmail.com>
|
||||
Todd Willey <todd@ansolabs.com>
|
||||
Tom Fifield <fifieldt@unimelb.edu.au>
|
||||
Tomasz 'Zen' Napierala <tomasz@napierala.org>
|
||||
Tres Henry <tres@treshenry.net>
|
||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||
Yuriy Taraday <yorik.sar@gmail.com>
|
||||
ZhongYue Luo <lzyeval@gmail.com>
|
||||
Ziad Sawalha <github@highbridgellc.com>
|
||||
ZHANG Hua <zhuadl@cn.ibm.com>
|
@ -4,6 +4,7 @@ recursive-include openstack_dashboard *.html *.js *.css *.less *.csv *.template
|
||||
recursive-include tools *.py *.sh
|
||||
|
||||
include AUTHORS
|
||||
include ChangeLog
|
||||
include LICENSE
|
||||
include Makefile
|
||||
include manage.py
|
||||
|
0
horizon/openstack/__init__.py
Normal file
0
horizon/openstack/__init__.py
Normal file
0
horizon/openstack/common/__init__.py
Normal file
0
horizon/openstack/common/__init__.py
Normal file
200
horizon/openstack/common/setup.py
Normal file
200
horizon/openstack/common/setup.py
Normal file
@ -0,0 +1,200 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Utilities with minimum-depends for use in setup.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from setuptools.command import sdist
|
||||
|
||||
|
||||
def parse_mailmap(mailmap='.mailmap'):
|
||||
mapping = {}
|
||||
if os.path.exists(mailmap):
|
||||
fp = open(mailmap, 'r')
|
||||
for l in fp:
|
||||
l = l.strip()
|
||||
if not l.startswith('#') and ' ' in l:
|
||||
canonical_email, alias = [x for x in l.split(' ')
|
||||
if x.startswith('<')]
|
||||
mapping[alias] = canonical_email
|
||||
return mapping
|
||||
|
||||
|
||||
def canonicalize_emails(changelog, mapping):
|
||||
"""Takes in a string and an email alias mapping and replaces all
|
||||
instances of the aliases in the string with their real email.
|
||||
"""
|
||||
for alias, email in mapping.iteritems():
|
||||
changelog = changelog.replace(alias, email)
|
||||
return changelog
|
||||
|
||||
|
||||
# Get requirements from the first file that exists
|
||||
def get_reqs_from_files(requirements_files):
|
||||
reqs_in = []
|
||||
for requirements_file in requirements_files:
|
||||
if os.path.exists(requirements_file):
|
||||
return open(requirements_file, 'r').read().split('\n')
|
||||
return []
|
||||
|
||||
|
||||
def parse_requirements(requirements_files=['requirements.txt',
|
||||
'tools/pip-requires']):
|
||||
requirements = []
|
||||
for line in get_reqs_from_files(requirements_files):
|
||||
# For the requirements list, we need to inject only the portion
|
||||
# after egg= so that distutils knows the package it's looking for
|
||||
# such as:
|
||||
# -e git://github.com/openstack/nova/master#egg=nova
|
||||
if re.match(r'\s*-e\s+', line):
|
||||
requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1',
|
||||
line))
|
||||
# such as:
|
||||
# http://github.com/openstack/nova/zipball/master#egg=nova
|
||||
elif re.match(r'\s*https?:', line):
|
||||
requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1',
|
||||
line))
|
||||
# -f lines are for index locations, and don't get used here
|
||||
elif re.match(r'\s*-f\s+', line):
|
||||
pass
|
||||
else:
|
||||
requirements.append(line)
|
||||
|
||||
return requirements
|
||||
|
||||
|
||||
def parse_dependency_links(requirements_files=['requirements.txt',
|
||||
'tools/pip-requires']):
|
||||
dependency_links = []
|
||||
# dependency_links inject alternate locations to find packages listed
|
||||
# in requirements
|
||||
for line in get_reqs_from_files(requirements_files):
|
||||
# skip comments and blank lines
|
||||
if re.match(r'(\s*#)|(\s*$)', line):
|
||||
continue
|
||||
# lines with -e or -f need the whole line, minus the flag
|
||||
if re.match(r'\s*-[ef]\s+', line):
|
||||
dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line))
|
||||
# lines that are only urls can go in unmolested
|
||||
elif re.match(r'\s*https?:', line):
|
||||
dependency_links.append(line)
|
||||
return dependency_links
|
||||
|
||||
|
||||
def write_requirements():
|
||||
venv = os.environ.get('VIRTUAL_ENV', None)
|
||||
if venv is not None:
|
||||
with open("requirements.txt", "w") as req_file:
|
||||
output = subprocess.Popen(["pip", "-E", venv, "freeze", "-l"],
|
||||
stdout=subprocess.PIPE)
|
||||
requirements = output.communicate()[0].strip()
|
||||
req_file.write(requirements)
|
||||
|
||||
|
||||
def _run_shell_command(cmd):
|
||||
output = subprocess.Popen(["/bin/sh", "-c", cmd],
|
||||
stdout=subprocess.PIPE)
|
||||
return output.communicate()[0].strip()
|
||||
|
||||
|
||||
def write_vcsversion(location):
|
||||
"""Produce a vcsversion dict that mimics the old one produced by bzr.
|
||||
"""
|
||||
if os.path.isdir('.git'):
|
||||
branch_nick_cmd = 'git branch | grep -Ei "\* (.*)" | cut -f2 -d" "'
|
||||
branch_nick = _run_shell_command(branch_nick_cmd)
|
||||
revid_cmd = "git rev-parse HEAD"
|
||||
revid = _run_shell_command(revid_cmd).split()[0]
|
||||
revno_cmd = "git log --oneline | wc -l"
|
||||
revno = _run_shell_command(revno_cmd)
|
||||
with open(location, 'w') as version_file:
|
||||
version_file.write("""
|
||||
# This file is automatically generated by setup.py, So don't edit it. :)
|
||||
version_info = {
|
||||
'branch_nick': '%s',
|
||||
'revision_id': '%s',
|
||||
'revno': %s
|
||||
}
|
||||
""" % (branch_nick, revid, revno))
|
||||
|
||||
|
||||
def write_git_changelog():
|
||||
"""Write a changelog based on the git changelog."""
|
||||
if os.path.isdir('.git'):
|
||||
git_log_cmd = 'git log --stat'
|
||||
changelog = _run_shell_command(git_log_cmd)
|
||||
mailmap = parse_mailmap()
|
||||
with open("ChangeLog", "w") as changelog_file:
|
||||
changelog_file.write(canonicalize_emails(changelog, mailmap))
|
||||
|
||||
|
||||
def generate_authors():
|
||||
"""Create AUTHORS file using git commits."""
|
||||
jenkins_email = 'jenkins@review.openstack.org'
|
||||
old_authors = 'AUTHORS.in'
|
||||
new_authors = 'AUTHORS'
|
||||
if os.path.isdir('.git'):
|
||||
# don't include jenkins email address in AUTHORS file
|
||||
git_log_cmd = ("git log --format='%aN <%aE>' | sort -u | "
|
||||
"grep -v " + jenkins_email)
|
||||
changelog = _run_shell_command(git_log_cmd)
|
||||
mailmap = parse_mailmap()
|
||||
with open(new_authors, 'w') as new_authors_fh:
|
||||
new_authors_fh.write(canonicalize_emails(changelog, mailmap))
|
||||
if os.path.exists(old_authors):
|
||||
with open(old_authors, "r") as old_authors_fh:
|
||||
new_authors_fh.write('\n' + old_authors_fh.read())
|
||||
|
||||
|
||||
def get_cmdclass():
|
||||
"""Return dict of commands to run from setup.py."""
|
||||
|
||||
cmdclass = dict()
|
||||
|
||||
class LocalSDist(sdist.sdist):
|
||||
"""Builds the ChangeLog and Authors files from VC first."""
|
||||
|
||||
def run(self):
|
||||
write_git_changelog()
|
||||
generate_authors()
|
||||
# sdist.sdist is an old style class, can't use super()
|
||||
sdist.sdist.run(self)
|
||||
|
||||
cmdclass['sdist'] = LocalSDist
|
||||
|
||||
# If Sphinx is installed on the box running setup.py,
|
||||
# enable setup.py to build the documentation, otherwise,
|
||||
# just ignore it
|
||||
try:
|
||||
from sphinx.setup_command import BuildDoc
|
||||
|
||||
class LocalBuildDoc(BuildDoc):
|
||||
def run(self):
|
||||
for builder in ['html', 'man']:
|
||||
self.builder = builder
|
||||
self.finalize_options()
|
||||
BuildDoc.run(self)
|
||||
cmdclass['build_sphinx'] = LocalBuildDoc
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
return cmdclass
|
@ -1,64 +0,0 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 OpenStack LLC
|
||||
# Copyright 2012 Nebula Inc
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import commands
|
||||
import unittest
|
||||
|
||||
|
||||
def parse_mailmap(mailmap='.mailmap'):
|
||||
mapping = {}
|
||||
if os.path.exists(mailmap):
|
||||
fp = open(mailmap, 'r')
|
||||
for l in fp:
|
||||
l = l.strip()
|
||||
if not l.startswith('#') and ' ' in l:
|
||||
canonical_email, alias = l.split(' ')
|
||||
mapping[alias] = canonical_email
|
||||
return mapping
|
||||
|
||||
|
||||
def str_dict_replace(s, mapping):
|
||||
for s1, s2 in mapping.iteritems():
|
||||
s = s.replace(s1, s2)
|
||||
return s
|
||||
|
||||
|
||||
class AuthorsTestCase(unittest.TestCase):
|
||||
def test_authors_up_to_date(self):
|
||||
path_bits = (os.path.dirname(__file__), '..', '..')
|
||||
root = os.path.normpath(os.path.join(*path_bits))
|
||||
contributors = set()
|
||||
missing = set()
|
||||
authors_file = open(os.path.join(root, 'AUTHORS'), 'r').read()
|
||||
|
||||
if os.path.exists(os.path.join(root, '.git')):
|
||||
mailmap = parse_mailmap(os.path.join(root, '.mailmap'))
|
||||
for email in commands.getoutput('git log --format=%ae').split():
|
||||
if not email:
|
||||
continue
|
||||
if "jenkins" in email and "openstack.org" in email:
|
||||
continue
|
||||
email = '<' + email + '>'
|
||||
contributors.add(str_dict_replace(email, mailmap))
|
||||
|
||||
for contributor in contributors:
|
||||
if not contributor in authors_file:
|
||||
missing.add(contributor)
|
||||
|
||||
self.assertTrue(len(missing) == 0,
|
||||
'%r not listed in AUTHORS file.' % missing)
|
7
openstack-common.conf
Normal file
7
openstack-common.conf
Normal file
@ -0,0 +1,7 @@
|
||||
[DEFAULT]
|
||||
|
||||
# The list of modules to copy from openstack-common
|
||||
modules=setup
|
||||
|
||||
# The base module to hold the copy of openstack.common
|
||||
base=horizon
|
@ -6,7 +6,7 @@ set -o errexit
|
||||
# Increment me any time the environment should be rebuilt.
|
||||
# This includes dependncy changes, directory renames, etc.
|
||||
# Simple integer secuence: 1, 2, 3...
|
||||
environment_version=17
|
||||
environment_version=18
|
||||
#--------------------------------------------------------#
|
||||
|
||||
function usage {
|
||||
|
61
setup.py
61
setup.py
@ -21,60 +21,22 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
from setuptools import setup, find_packages
|
||||
import setuptools
|
||||
from horizon import version
|
||||
|
||||
from horizon.openstack.common import setup
|
||||
|
||||
requires = setup.parse_requirements()
|
||||
depend_links = setup.parse_dependency_links()
|
||||
tests_require = setup.parse_requirements(['tools/test-requires'])
|
||||
|
||||
ROOT = os.path.dirname(__file__)
|
||||
PIP_REQUIRES = os.path.join(ROOT, "tools", "pip-requires")
|
||||
TEST_REQUIRES = os.path.join(ROOT, "tools", "test-requires")
|
||||
|
||||
|
||||
def parse_requirements(*filenames):
|
||||
"""
|
||||
We generate our install_requires from the pip-requires and test-requires
|
||||
files so that we don't have to maintain the dependency definitions in
|
||||
two places.
|
||||
"""
|
||||
requirements = []
|
||||
for f in filenames:
|
||||
for line in open(f, 'r').read().split('\n'):
|
||||
# Comment lines. Skip.
|
||||
if re.match(r'(\s*#)|(\s*$)', line):
|
||||
continue
|
||||
# Editable matches. Put the egg name into our reqs list.
|
||||
if re.match(r'\s*-e\s+', line):
|
||||
pkg = re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', line)
|
||||
requirements.append("%s" % pkg)
|
||||
# File-based installs not supported/needed. Skip.
|
||||
elif re.match(r'\s*-f\s+', line):
|
||||
pass
|
||||
else:
|
||||
requirements.append(line)
|
||||
return requirements
|
||||
|
||||
|
||||
def parse_dependency_links(*filenames):
|
||||
"""
|
||||
We generate our dependency_links from the pip-requires and test-requires
|
||||
files for the dependencies pulled from github (prepended with -e).
|
||||
"""
|
||||
dependency_links = []
|
||||
for f in filenames:
|
||||
for line in open(f, 'r').read().split('\n'):
|
||||
if re.match(r'\s*-[ef]\s+', line):
|
||||
line = re.sub(r'\s*-[ef]\s+', '', line)
|
||||
line = re.sub(r'\s*git\+https', 'http', line)
|
||||
line = re.sub(r'\.git#', '/tarball/master#', line)
|
||||
dependency_links.append(line)
|
||||
return dependency_links
|
||||
|
||||
|
||||
def read(fname):
|
||||
return open(os.path.join(ROOT, fname)).read()
|
||||
|
||||
|
||||
setup(name="horizon",
|
||||
setuptools.setup(name="horizon",
|
||||
version=version.canonical_version_string(),
|
||||
url='https://github.com/openstack/horizon/',
|
||||
license='Apache 2.0',
|
||||
@ -82,12 +44,13 @@ setup(name="horizon",
|
||||
long_description=read('README.rst'),
|
||||
author='OpenStack',
|
||||
author_email='horizon@lists.launchpad.net',
|
||||
packages=find_packages(),
|
||||
packages=setuptools.find_packages(),
|
||||
cmdclass=setup.get_cmdclass(),
|
||||
include_package_data=True,
|
||||
install_requires=requires,
|
||||
tests_require=tests_require,
|
||||
dependency_links=depend_links,
|
||||
zip_safe=False,
|
||||
install_requires=parse_requirements(PIP_REQUIRES),
|
||||
tests_require=parse_requirements(TEST_REQUIRES),
|
||||
dependency_links=parse_dependency_links(PIP_REQUIRES, TEST_REQUIRES),
|
||||
classifiers=['Development Status :: 4 - Beta',
|
||||
'Framework :: Django',
|
||||
'Intended Audience :: Developers',
|
||||
|
@ -4,6 +4,6 @@ python-cloudfiles
|
||||
python-dateutil
|
||||
|
||||
# Horizon Non-pip Requirements
|
||||
-e git+https://github.com/openstack/python-novaclient.git#egg=python-novaclient
|
||||
-e git+https://github.com/openstack/python-keystoneclient.git#egg=python-keystoneclient
|
||||
-e git+https://github.com/openstack/python-glanceclient.git#egg=python-glanceclient
|
||||
https://github.com/openstack/python-novaclient/zipball/master#egg=python-novaclient
|
||||
https://github.com/openstack/python-keystoneclient/zipball/master#egg=python-keystoneclient
|
||||
https://github.com/openstack/python-glanceclient/zipball/master#egg=python-glanceclient
|
||||
|
@ -1,14 +1,17 @@
|
||||
distribute>=0.6.24
|
||||
|
||||
# Testing Requirements
|
||||
coverage
|
||||
django-nose
|
||||
mox
|
||||
netaddr
|
||||
nose
|
||||
nose-exclude
|
||||
nosexcover
|
||||
openstack.nose_plugin
|
||||
pep8
|
||||
pylint
|
||||
distribute>=0.6.24
|
||||
selenium
|
||||
netaddr
|
||||
|
||||
# Docs Requirements
|
||||
sphinx
|
||||
|
46
tox.ini
Normal file
46
tox.ini
Normal file
@ -0,0 +1,46 @@
|
||||
[tox]
|
||||
envlist = py26,py27,pep8
|
||||
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
NOSE_WITH_OPENSTACK=1
|
||||
NOSE_OPENSTACK_COLOR=1
|
||||
NOSE_OPENSTACK_RED=0.05
|
||||
NOSE_OPENSTACK_YELLOW=0.025
|
||||
NOSE_OPENSTACK_SHOW_ELAPSED=1
|
||||
deps = -r{toxinidir}/tools/pip-requires
|
||||
-r{toxinidir}/tools/test-requires
|
||||
commands = /bin/bash run_tests.sh -N
|
||||
|
||||
[testenv:pep8]
|
||||
deps = pep8
|
||||
commands = /bin/bash run_tests.sh -N --pep8
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
commands = /bin/bash run_tests.sh -N --coverage
|
||||
|
||||
[tox:jenkins]
|
||||
downloadcache = ~/cache/pip
|
||||
|
||||
[testenv:jenkins26]
|
||||
setenv = NOSE_WITH_XUNIT=1
|
||||
basepython = python2.6
|
||||
|
||||
[testenv:jenkins27]
|
||||
setenv = NOSE_WITH_XUNIT=1
|
||||
basepython = python2.7
|
||||
|
||||
[testenv:jenkinspep8]
|
||||
setenv = NOSE_WITH_XUNIT=1
|
||||
commands = /bin/bash run_tests.sh -N --pep8
|
||||
|
||||
[testenv:jenkinscover]
|
||||
setenv = NOSE_WITH_XUNIT=1
|
||||
commands = /bin/bash run_tests.sh -N --coverage
|
||||
|
||||
[testenv:jenkinsvenv]
|
||||
setenv = NOSE_WITH_XUNIT=1
|
||||
commands = {posargs}
|
Loading…
Reference in New Issue
Block a user