Skip to content

Commit

Permalink
Merge 9d6a63b into 214c360
Browse files Browse the repository at this point in the history
  • Loading branch information
mriehl committed Aug 6, 2014
2 parents 214c360 + 9d6a63b commit f85a15e
Show file tree
Hide file tree
Showing 7 changed files with 367 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# This file is part of PyBuilder
#
# Copyright 2011 The PyBuilder Team
#
# 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 unittest
from os.path import join

from integrationtest_support import IntegrationTestSupport


class Test (IntegrationTestSupport):

def test(self):
requirements = join(self.tmp_directory, "requirements.txt")
self.write_build_file("""
from pybuilder.core import use_plugin, init
use_plugin("python.core")
use_plugin("python.distutils")
name = "integration-test"
default_task = "publish"
@init
def init (project):
project.depends_on("spam")
project.depends_on_requirements("{0}")
project.depends_on("pyassert", url="https://github.com/downloads/halimath/pyassert/pyassert-0.2.2.tar.gz")
project.depends_on("eggs", "==0.2.3")
project.build_depends_on("eggy")
""".format(requirements))
self.create_directory("src/main/python/spam")
self.write_file("requirements.txt", """
awesome>=1.3.37
foo==42""")
self.write_file("src/main/python/standalone_module.py")
self.write_file("src/main/python/spam/__init__.py", "")
self.write_file("src/main/python/spam/eggs.py", """
def spam ():
pass
""")

reactor = self.prepare_reactor()
reactor.build()

self.assert_directory_exists("target/dist/integration-test-1.0-SNAPSHOT")
self.assert_directory_exists("target/dist/integration-test-1.0-SNAPSHOT/spam")
self.assert_file_exists("target/dist/integration-test-1.0-SNAPSHOT/standalone_module.py")
self.assert_file_empty("target/dist/integration-test-1.0-SNAPSHOT/spam/__init__.py")
self.assert_file_content("target/dist/integration-test-1.0-SNAPSHOT/spam/eggs.py", """
def spam ():
pass
""")

setup_py = "target/dist/integration-test-1.0-SNAPSHOT/setup.py"

self.assert_file_exists(setup_py)
self.assert_file_permissions(0o755, setup_py)
self.assert_file_content(setup_py, """#!/usr/bin/env python
from setuptools import setup
if __name__ == '__main__':
setup(
name = 'integration-test',
version = '1.0-SNAPSHOT',
description = '''''',
long_description = '''''',
author = "",
author_email = "",
license = '',
url = '',
scripts = [],
packages = ['spam'],
py_modules = ['standalone_module'],
classifiers = ['Development Status :: 3 - Alpha', 'Programming Language :: Python'],
entry_points={
'console_scripts':
[]
},
# data files
# package data
install_requires = [ "eggs==0.2.3", "spam", "awesome>=1.3.37", "foo==42" ],
dependency_links = [ "https://github.com/downloads/halimath/pyassert/pyassert-0.2.2.tar.gz" ],
zip_safe=True
)
""")


if __name__ == "__main__":
unittest.main()
34 changes: 34 additions & 0 deletions src/main/python/pybuilder/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ def __init__(self, name, version=None, url=None):
self.url = url

def __eq__(self, other):
if not isinstance(other, Dependency):
return False
return self.name == other.name and self.version == other.version and self.url == other.url

def __ne__(self, other):
Expand All @@ -206,9 +208,35 @@ def __hash__(self):
return 13 * hash(self.name) + 17 * hash(self.version)

def __lt__(self, other):
if not isinstance(other, Dependency):
return True
return self.name < other.name


class RequirementsFile(object):
"""
Represents all dependencies in a requirements file (requirements.txt).
"""
def __init__(self, filename):
self.name = filename

def __eq__(self, other):
if not isinstance(other, RequirementsFile):
return False
return self.name == other.name

def __ne__(self, other):
return not(self == other)

def __lt__(self, other):
if not isinstance(other, RequirementsFile):
return False
return self.name < other.name

def __hash__(self):
return 42 * hash(self.name)


class Project(object):
"""
Descriptor for a project to be built. A project has a number of attributes
Expand Down Expand Up @@ -296,6 +324,12 @@ def depends_on(self, name, version=None, url=None):
def build_depends_on(self, name, version=None, url=None):
self._build_dependencies.add(Dependency(name, version, url))

def depends_on_requirements(self, file):
self._install_dependencies.add(RequirementsFile(file))

def build_depends_on_requirements(self, file):
self._build_dependencies.add(RequirementsFile(file))

@property
def manifest_included_files(self):
return self._manifest_included_files
Expand Down
48 changes: 41 additions & 7 deletions src/main/python/pybuilder/plugins/python/distutils_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
except ImportError as e:
from io import StringIO

from pybuilder.core import after, before, use_plugin, init
from pybuilder.core import (after,
before,
use_plugin,
init,
RequirementsFile,
Dependency)
from pybuilder.errors import BuildFailedException
from pybuilder.utils import as_list

Expand Down Expand Up @@ -185,24 +190,53 @@ def build_binary_distribution(project, logger):
"Error while executing setup command %s", command)


def strip_comments(requirements):
return [requirement for requirement in requirements
if not requirement.strip().startswith("#")]


def quote(requirements):
return ['"%s"' % requirement for requirement in requirements]


def flatten_and_quote(requirements_file):
with open(requirements_file.name, 'r') as requirements_file:
requirements = [requirement.strip("\n") for requirement in requirements_file.readlines()]
requirements = [requirement for requirement in requirements if requirement]
return quote(strip_comments(requirements))


def format_single_dependency(dependency):
return '"%s%s"' % (dependency.name, build_dependency_version_string(dependency))


def build_install_dependencies_string(project):
dependencies = [
dependency for dependency in project.dependencies if not dependency.url]
if not dependencies:
dependency for dependency in project.dependencies
if isinstance(dependency, Dependency)
and not dependency.url]
requirements = [
requirements for requirements in project.dependencies
if isinstance(requirements, RequirementsFile)]
if not dependencies and not requirements:
return ""

def format_single_dependency(dependency):
return '"%s%s"' % (dependency.name, build_dependency_version_string(dependency))
dependencies = [format_single_dependency(dependency) for dependency in dependencies]
requirements = [strip_comments(flatten_and_quote(requirement)) for requirement in requirements]
flattened_requirements = [dependency for dependency_list in requirements for dependency in dependency_list]

dependencies.extend(flattened_requirements)

result = "install_requires = [ "
result += ", ".join(map(format_single_dependency, dependencies))
result += ", ".join(dependencies)
result += " ],"
return result


def build_dependency_links_string(project):
dependency_links = [
dependency for dependency in project.dependencies if dependency.url]
dependency for dependency in project.dependencies
if isinstance(dependency, Dependency) and dependency.url]
if not dependency_links:
return ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@

import sys

from pybuilder.core import before, after, task, description, use_plugin, init
from pybuilder.core import (before,
after,
task,
description,
use_plugin,
init,
RequirementsFile)
from pybuilder.errors import BuildFailedException
from pybuilder.utils import assert_can_execute, execute_command, mkdir
from pybuilder.plugins.python.setuptools_plugin_helper import build_dependency_version_string
Expand Down Expand Up @@ -83,14 +89,18 @@ def create_install_log_directory(logger, project):


def install_dependency(logger, project, dependency):
logger.info("Installing dependency '%s'%s", dependency.name, " from %s" % dependency.url if dependency.url else "")
url = getattr(dependency, "url", None)
logger.info("Installing dependency '%s'%s", dependency.name,
" from %s" % url if url else "")
log_file = project.expand_path("$dir_install_logs", dependency.name)

if sys.platform.startswith("win"):
dependency = as_pip_argument(dependency)
# we can't use quotes on windows
pip_dependency = as_pip_argument(dependency)
else:
dependency = "'{0}'".format(as_pip_argument(dependency))
pip_command_line = "pip install {0}{1}".format(build_pip_install_options(project, dependency), dependency)
# on linux we need quotes because version pinning (>=) would be an IO redirect
pip_dependency = "'{0}'".format(as_pip_argument(dependency))
pip_command_line = "pip install {0}{1}".format(build_pip_install_options(project, pip_dependency), pip_dependency)
exit_code = execute_command(pip_command_line, log_file, shell=True)
if exit_code != 0:
if project.get_property("verbose"):
Expand Down Expand Up @@ -125,6 +135,8 @@ def build_pip_install_options(project, dependency):


def as_pip_argument(dependency):
if isinstance(dependency, RequirementsFile):
return "-r{0}".format(dependency.name)
if dependency.url:
return dependency.url
return "{0}{1}".format(dependency.name, build_dependency_version_string(dependency))
Expand Down
94 changes: 93 additions & 1 deletion src/unittest/python/core_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
from mockito import when, verify, unstub

from pybuilder.core import (Project, Logger, init, INITIALIZER_ATTRIBUTE,
ENVIRONMENTS_ATTRIBUTE, task, description)
ENVIRONMENTS_ATTRIBUTE, task, description,
Dependency, RequirementsFile)
from pybuilder.errors import MissingPropertyException


Expand Down Expand Up @@ -488,3 +489,94 @@ def task_with_description():

self.assertEqual(task_with_description._python_builder_task, True)
self.assertEqual(task_with_description._python_builder_description, "any-description")


class RequirementsFileTests(unittest.TestCase):

def test_requirements_file_should_be_equal_to_itself(self):
requirements_file = RequirementsFile("requirements.txt")
self.assertTrue(requirements_file == requirements_file)

def test_requirements_file_should_not_be_unequal_to_itself(self):
requirements_file = RequirementsFile("requirements.txt")
self.assertFalse(requirements_file != requirements_file)

def test_requirements_file_should_not_be_equal_to_other_when_names_differ(self):
requirements_file = RequirementsFile("requirements.txt")
dev_requirements_file = RequirementsFile("requirements-dev.txt")
self.assertFalse(requirements_file == dev_requirements_file)

def test_requirements_file_should_be_unequal_to_other_when_names_differ(self):
requirements_file = RequirementsFile("requirements.txt")
dev_requirements_file = RequirementsFile("requirements-dev.txt")
self.assertTrue(requirements_file != dev_requirements_file)

def test_requirements_file_should_be_lesser_than_other_when_name_is_lesser(self):
requirements_file = RequirementsFile("requirements.txt")
dev_requirements_file = RequirementsFile("requirements-dev.txt")
self.assertTrue(requirements_file > dev_requirements_file)


class DependencyTests(unittest.TestCase):

def test_requirements_file_should_be_equal_to_itself(self):
dependency = Dependency("foo")
self.assertTrue(dependency == dependency)

def test_dependency_should_not_be_unequal_to_itself(self):
dependency = Dependency("foo")
self.assertFalse(dependency != dependency)

def test_dependency_should_not_be_equal_to_other_when_names_differ(self):
dependency = Dependency("foo")
other_dependency = Dependency("foa")
self.assertFalse(dependency == other_dependency)

def test_dependency_should_be_unequal_to_other_when_names_differ(self):
dependency = Dependency("foo")
other_dependency = Dependency("foa")
self.assertTrue(dependency != other_dependency)

def test_dependency_should_be_lesser_than_other_when_name_is_lesser(self):
dependency = Dependency("foo")
other_dependency = Dependency("foa")
self.assertTrue(dependency > other_dependency)


class DependencyAndRequirementsFileTests(unittest.TestCase):

def test_requirements_file_should_not_be_equal_to_dependency(self):
dependency = Dependency("foo")
requirements = RequirementsFile("requirements.txt")

self.assertFalse(dependency == requirements)

def test_requirements_file_should_not_be_equal_to_dependency_even_when_name_matches(self):
dependency = Dependency("foo")
requirements = RequirementsFile("foo")

self.assertFalse(dependency == requirements)

def test_requirements_file_should_be_unequal_to_dependency(self):
dependency = Dependency("foo")
requirements = RequirementsFile("requirements.txt")

self.assertTrue(dependency != requirements)

def test_requirements_file_should_be_unequal_to_dependency_even_when_name_matches(self):
dependency = Dependency("foo")
requirements = RequirementsFile("foo")

self.assertTrue(dependency != requirements)

def test_requirements_should_always_be_greater_than_dependencies(self):
dependency = Dependency("foo")
requirements = RequirementsFile("requirements.txt")

self.assertTrue(requirements > dependency)

def test_requirements_should_always_be_greater_than_dependencies_even_when_name_matches(self):
dependency = Dependency("foo")
requirements = RequirementsFile("foo")

self.assertTrue(requirements > dependency)

0 comments on commit f85a15e

Please sign in to comment.