Support platform-specific requirements files

This patch adds support for choosing a requirements file, based on the
current OS, with the format 'requirements-{osname}'. This can be combined
with the current approach of choosing a requirement file based on the
Python version. The motivation for this is to replace conditional
choosing of packages inside setup.py.

Change-Id: I30c56082bb9b9bcd80128eedcef17b6beb793cf8
This commit is contained in:
Claudiu Popa 2014-11-24 11:04:43 +02:00
parent e0d2674102
commit 8cdb41cf12
3 changed files with 62 additions and 6 deletions

View File

@ -107,11 +107,21 @@ You can also have a requirement file for each specific major version of
Python. If you want to have a different package list for Python 3, just drop
a requirements-py3.txt, and it will be used instead.
The requirement files are tried in that order (N being the Python major
version number used to install the package):
It's also possible to select a requirement file specific for an OS. The format
is requirements-{osname}.txt, where ``{osname}`` is the equivalent of
``platform.system()``. The two approaches, Python version and OS version, can
be combined.
The requirement files are tried in that order (N being the Python major
version number used to install the package and OS being the current
platform's name in lowercase, retrieved with ``platform.system()``):
* requirements-OS-pyN.txt
* tools/pip-requires-OS-pyN
* requirements-OS.txt
* tools/pip-requires-OS
* requirements-pyN.txt
* tools/pip-requires-py3
* tools/pip-requires-pyN
* requirements.txt
* tools/pip-requires

View File

@ -24,8 +24,11 @@ from distutils.command import install as du_install
import distutils.errors
from distutils import log
import email
import functools
import io
import itertools
import os
import platform
import re
import subprocess
import sys
@ -56,10 +59,26 @@ def get_requirements_files():
# Returns a list composed of:
# - REQUIREMENTS_FILES with -py2 or -py3 in the name
# (e.g. requirements-py3.txt)
# - REQUIREMENTS_FILES with -{platform.system} in the name
# (e.g. requirements-windows.txt)
# - REQUIREMENTS_FILES with both Python version and platform's
# system in the name
# (e.g. requirements-freebsd-py2.txt)
# - REQUIREMENTS_FILES
return (list(map(('-py' + str(sys.version_info[0])).join,
map(os.path.splitext, REQUIREMENTS_FILES)))
+ list(REQUIREMENTS_FILES))
pyversion = sys.version_info[0]
system = platform.system().lower()
parts = list(map(os.path.splitext, REQUIREMENTS_FILES))
version_cb = functools.partial("{1}-py{0}{2}".format, pyversion)
platform_cb = functools.partial("{1}-{0}{2}".format, system)
both_cb = functools.partial("{2}-{0}-py{1}{3}".format, system, pyversion)
return list(itertools.chain(
itertools.starmap(both_cb, parts),
itertools.starmap(platform_cb, parts),
itertools.starmap(version_cb, parts),
REQUIREMENTS_FILES,
))
def append_text_list(config, key, text_list):

View File

@ -39,6 +39,7 @@
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
import os
import sys
import tempfile
import fixtures
@ -214,6 +215,32 @@ class TestNestedRequirements(base.BaseTestCase):
self.assertEqual(result, ['pbr'])
class TestGetRequirements(base.BaseTestCase):
def test_get_requirements_file(self):
platforms = ['Windows', 'Freebsd', 'Darwin', 'Linux']
version = sys.version_info[0]
with mock.patch('platform.system') as platform_system:
platform_system.side_effect = platforms
for platform in map(str.lower, platforms):
expected = [
'requirements-{plat}-py{ver}.txt'.format(
plat=platform, ver=version),
'tools/pip-requires-{plat}-py{ver}'.format(
plat=platform, ver=version),
'requirements-{0}.txt'.format(platform),
'tools/pip-requires-{0}'.format(platform),
'requirements-py{0}.txt'.format(version),
'tools/pip-requires-py{0}'.format(version),
'requirements.txt',
'tools/pip-requires',
]
files = packaging.get_requirements_files()
self.assertEqual(expected, files)
class TestVersions(base.BaseTestCase):
scenarios = [