# Copyright (c) 2014 Spotify AB
# This file is part of dh-virtualenv.
# dh-virtualenv is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 2 of the
# License, or (at your option) any later version.
# dh-virtualenv is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with dh-virtualenv. If not, see
# <http://www.gnu.org/licenses/>.
"""Helpers to handle debhelper command line options."""
import os
import warnings
from optparse import OptionParser, SUPPRESS_HELP, OptionValueError
from . import __version__ as version
[docs]
class DebhelperOptionParser(OptionParser):
"""Special OptionParser for handling Debhelper options.
Basically this means converting -O--option to --option before
parsing.
"""
[docs]
def parse_args(self, args=None, values=None):
args = [o[2:] if (o.startswith('-O-') and self.has_option(o[2:])) else o
for o in self._get_args(args)]
args.extend(os.environ.get('DH_OPTIONS', '').split())
# Unfortunately OptionParser is an old style class :(
options, args = OptionParser.parse_args(self, args, values)
# Like debhelper, DH_VERBOSE=1 is equivalent to --verbose
if (os.environ.get('DH_VERBOSE') == '1'
and getattr(options, 'verbose', None) is not None):
options.verbose = True
return options, args
# Deprecated options and the warning emitted when they are used
DEPRECATED_OPTIONS = {
'--pypi-url': 'Use of --pypi-url is deprecated. Use --index-url instead',
'--no-test': ('Use of --no-test is deprecated and has no effect. Use '
'--setuptools-test if you want to execute `setup.py test` '
'during package build.'),
'--setuptools-test': ('Use of --setuptools-test is deprecated: '
'`setup.py test` was removed in setuptools 72 and '
'only works if the virtualenv contains an older '
'setuptools.'),
}
def _warn_if_deprecated(opt_str):
message = DEPRECATED_OPTIONS.get(opt_str)
if message:
# Make sure the DeprecationWarning is shown, it is hidden by default
with warnings.catch_warnings():
warnings.simplefilter('default')
warnings.warn(message, DeprecationWarning)
def _set_index_url(option, opt_str, value, parser, *args, **kwargs):
"""Callback for --index-url and its deprecated alias --pypi-url."""
_warn_if_deprecated(opt_str)
if parser.values.index_url:
# We've already set the index_url, which means that we have both
# --index-url and --pypi-url passed in.
raise OptionValueError('Deprecated --pypi-url and the new '
'--index-url are mutually exclusive')
parser.values.index_url = value
def _set_setuptools_test(option, opt_str, value, parser, *args, **kwargs):
"""Callback for --setuptools-test and the deprecated no-op --no-test."""
_warn_if_deprecated(opt_str)
if getattr(parser.values, '_test_flag_seen', None):
raise OptionValueError('Deprecated --no-test and the new '
'--setuptools-test are mutually exclusive')
parser.values.setuptools_test = opt_str != '--no-test'
setattr(parser.values, '_test_flag_seen', True)
def _set_builtin_venv(
option, opt_str, value, parser, *args, **kwargs
):
if parser.values.setuptools:
raise OptionValueError(
'--setuptools flag is not supported by builtin venv module'
)
else:
parser.values.builtin_venv = True
def _set_setuptools(
option, opt_str, value, parser, *args, **kwargs
):
if parser.values.builtin_venv:
raise OptionValueError(
'--setuptools flag is not supported by builtin venv module'
)
else:
parser.values.setuptools = True
[docs]
def get_default_parser():
usage = '%prog [options]'
parser = DebhelperOptionParser(usage, version='%prog ' + version)
parser.add_option('-p', '--package', action='append', metavar='PACKAGE',
help='Act on the package(s) named PACKAGE')
parser.add_option('-N', '--no-package', action='append', metavar='PACKAGE',
help='Do not act on the specified package(s)')
parser.add_option('-v', '--verbose', action='store_true',
default=False, help='Turn on verbose mode')
parser.add_option('-s', '--setuptools', action='callback',
dest='setuptools',
callback=_set_setuptools,
default=False, help='Use Setuptools instead of Distribute')
parser.add_option('--extra-index-url', action='append', metavar='URL',
help='Extra index URL(s) to pass to pip.',
default=[])
parser.add_option('--preinstall', action='append', metavar='PACKAGE',
help=('Package(s) to install before processing '
'requirements.txt.'),
default=[])
parser.add_option('--extras', action='append', metavar='NAME',
help=('Activate one or more extras of the main package.'),
default=[])
parser.add_option('--pip-tool', default='pip', metavar='EXECUTABLE',
help="Executable that will be used to install "
"requirements after the preinstall stage. Usually "
"you'll install this program by using the --preinstall "
"argument. The replacement is expected to be found in "
"the virtualenv's bin/ directory.")
parser.add_option('--upgrade-pip', action='store_true', default=False,
help='Upgrade pip to the latest available version')
parser.add_option('--upgrade-pip-to', default='', metavar='VERSION',
help='Upgrade pip to a specific version')
parser.add_option('--extra-pip-arg', action='append', metavar='ARG',
help='One or more extra args for the pip binary.'
'You can use this flag multiple times to pass in'
' parameters to pip.', default=[])
parser.add_option('--extra-virtualenv-arg', action='append', metavar='ARG',
help='One or more extra args for the virtualenv binary.'
'You can use this flag multiple times to pass in'
' parameters to the virtualenv binary.', default=[])
parser.add_option('--index-url', metavar='URL',
help='Base URL of the PyPI server',
action='callback',
type='string',
dest='index_url',
callback=_set_index_url)
parser.add_option('--python', metavar='EXECUTABLE',
help='The Python command to use')
parser.add_option('--builtin-venv', action='callback',
dest='builtin_venv',
callback=_set_builtin_venv,
help='Use the built-in venv module. Only works on '
'Python 3.4 and later.')
parser.add_option('-D', '--sourcedirectory', dest='sourcedirectory',
help='The source directory')
parser.add_option('-n', '--noscripts', action='store_false', dest='autoscripts',
help="Do not modify postinst and similar scripts.",
default=True)
parser.add_option('-S', '--use-system-packages', action='store_true',
dest='use_system_packages',
help="Set the --system-site-packages flag in virtualenv "
"creation, allowing you to use system packages.",
default=False)
parser.add_option('--skip-install', action='store_true',
default=False,
dest='skip_install',
help="Skip running pip install within the source directory.")
parser.add_option('--install-suffix', metavar='DIRNAME',
dest='install_suffix',
help="Override installation path suffix")
parser.add_option('--requirements', metavar='FILEPATH',
dest='requirements_filename',
help='Specify the filename for requirements.txt',
default='requirements.txt')
parser.add_option('--setuptools-test',
dest='setuptools_test',
default=False,
action='callback',
help='Run `setup.py test` when building the package. '
'Deprecated: needs setuptools < 72 in the virtualenv',
callback=_set_setuptools_test)
# Ignore user-specified option bundles
parser.add_option('-O', help=SUPPRESS_HELP)
parser.add_option('-a', '--arch', dest="arch",
help=("Act on architecture dependent packages that "
"should be built for the build architecture. "
"This option is ignored"),
action="store_true")
parser.add_option('-i', '--indep', dest="indep",
help=("Act on all architecture independent packages. "
"This option is ignored"),
action="store_true")
# Deprecated options
parser.add_option('--pypi-url', metavar='URL',
help=('!!DEPRECATED, use --index-url instead!! '
'Base URL of the PyPI server'),
action='callback',
dest='index_url',
type='string',
callback=_set_index_url)
parser.add_option('--no-test',
help="!!DEPRECATED, this command has no effect. "
"See --setuptools-test!! "
"Don't run tests for the package. Useful "
"for example when you have packaged with distutils.",
action='callback',
callback=_set_setuptools_test)
return parser