/usr/share/pyshared/stsci/distutils/hooks.py is in python-stsci.distutils 0.3.6-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | from __future__ import with_statement
import datetime
import glob
import os
import string
import sys
from distutils import log
try:
from packaging.util import split_multiline
except ImportError:
try:
from distutils2.util import split_multiline
except ImportError:
from d2to1.util import split_multiline
try:
# python 2
reload
except NameError:
# python 3
from imp import reload
from .svnutils import get_svn_info, get_svn_version
from .versionutils import (package_uses_version_py, clean_version_py,
update_setup_datetime, VERSION_PY_TEMPLATE)
# For each version.py that we create, we will note the version of
# stsci.distutils (this package) that created it. The problem is
# when the package being installed is stsci.distutils -- we don't
# know the version yet. So, if we can't import the version (because
# it does not exist yet), we declare it to be None and special case
# it later.
try :
from . import version as my_version
except ImportError :
my_version = None
def is_display_option(ignore=None):
"""A hack to test if one of the arguments passed to setup.py is a display
argument that should just display a value and exit. If so, don't bother
running this hook (this capability really ought to be included with
distutils2).
Optionally, ignore may contain a list of display options to ignore in this
check. Each option in the ignore list must contain the correct number of
dashes.
"""
from setuptools.dist import Distribution
# If there were no arguments in argv (aside from the script name) then this
# is an implied display opt
if len(sys.argv) < 2:
return True
display_opts = ['--command-packages', '--help', '-h']
for opt in Distribution.display_options:
display_opts.append('--' + opt[0])
for arg in sys.argv:
if arg in display_opts and arg not in ignore:
return True
return False
# TODO: With luck this can go away soon--packaging now supports adding the cwd
# to sys.path for running setup_hooks. But it also needs to support adding
# packages_root. Also, it currently does not support adding cwd/packages_root
# to sys.path for pre/post-command hooks, so that needs to be fixed.
def use_packages_root(config):
"""
Adds the path specified by the 'packages_root' option, or the current path
if 'packages_root' is not specified, to sys.path. This is particularly
useful, for example, to run setup_hooks or add custom commands that are in
your package's source tree.
Use this when the root of your package source tree is not in
the same directory with the setup.py
Config Usage::
[files]
packages_root = lib
# for installing pkgname from lib/pkgname/*.py
[global]
setup_hooks = stsci.distutils.hooks.use_packages_root
"""
if 'files' in config and 'packages_root' in config['files']:
root = config['files']['packages_root']
else:
root = ''
if root not in sys.path:
if root and sys.path[0] == '':
sys.path.insert(1, root)
else:
sys.path.insert(0, root)
# Reload the stsci namespace package in case any new paths can be added to
# it from the new sys.path entry; depending on how the namespace packages
# are installed this may fail--specifically if it's using the old
# setuptools-based .pth approach there is not importable package called
# 'stsci' that can be imported by itself.
if 'stsci' in sys.modules:
mod = sys.modules['stsci']
if sys.version_info[:2] >= (3, 3) and not hasattr(mod, '__loader__'):
# Workaround for Python bug #17099 on Python 3.3, where reload()
# crashes if a module doesn't have an __loader__ attribute
del sys.modules['stsci']
try:
import stsci
except ImportError:
pass
else:
try :
reload(sys.modules['stsci'])
except ImportError:
# doesn't seem to bother anything when this reload() fails
pass
def tag_svn_revision(config):
"""
A setup_hook to add the SVN revision of the current working copy path to
the package version string, but only if the version ends in .dev.
For example, ``mypackage-1.0.dev`` becomes ``mypackage-1.0.dev1234``. This
is in accordance with the version string format standardized by PEP 386.
This should be used as a replacement for the ``tag_svn_revision`` option to
the egg_info command. This hook is more compatible with
packaging/distutils2, which does not include any VCS support. This hook is
also more flexible in that it turns the revision number on/off depending on
the presence of ``.dev`` in the version string, so that it's not
automatically added to the version in final releases.
This hook does require the ``svnversion`` command to be available in order
to work. It does not examine the working copy metadata directly.
Config Usage::
[global]
setup_hooks = stsci.distutils.hooks.tag_svn_revision
You should write exactly this in your package's ``__init__.py``::
from .version import *
"""
if 'metadata' in config and 'version' in config['metadata']:
metadata = config['metadata']
version = metadata['version']
# Don't add an svn revision unless the version ends with .dev
if not version.endswith('.dev'):
return
# First try to get the revision by checking for it in an existing
# .version module
package_dir = config.get('files', {}).get('packages_root', '')
packages = config.get('files', {}).get('packages', '')
packages = split_multiline(packages)
rev = None
for package in packages:
version_py = package_uses_version_py(package_dir, package)
if not version_py:
continue
try:
mod = __import__(package + '.version',
fromlist='__svn_revision__')
except ImportError:
mod = None
if mod is not None and hasattr(mod, '__svn_revision__'):
rev = mod.__svn_revision__
break
# Cleanup
names = set([package, package + '.'])
for modname in list(sys.modules):
if modname == package or modname.startswith(package + '.'):
del sys.modules[modname]
if rev is None:
# A .version module didn't exist or was incomplete; try calling
# svnversion directly
rev = get_svn_version()
if not rev:
return
if ':' in rev:
rev, _ = rev.split(':', 1)
while rev and rev[-1] not in string.digits:
rev = rev[:-1]
try:
rev = int(rev)
except (ValueError, TypeError):
return
metadata['version'] ='%s%d' % (version, rev)
def _version_hook(function_name, package_dir, packages, name, version, vdate):
"""This command hook creates an version.py file in each package that
requires it. This is by determining if the package's ``__init__.py`` tries
to import or import from the version module.
version.py will not be created in packages that don't use it. It should
only be used by the top-level package of the project.
Don't use this function directly--instead use :func:`version_setup_hook` or
:func:`version_pre_command_hook` which know how to retrieve the required
metadata depending on the context they are run in.
Not called directly from the config file. See :func:`version_setup_hook`.
"""
# Strip any revision info from version; that will be handled separately
if '-' in version:
version = version.split('-', 1)[0]
for package in packages:
version_py = package_uses_version_py(package_dir, package)
if not version_py:
continue
rev = get_svn_version()
if ((not rev or not rev[0] in string.digits) and
os.path.exists(version_py)):
# If were unable to determine an SVN revision and the version.py
# already exists, just update the __setup_datetime__ and leave the
# rest of the file untouched
update_setup_datetime(version_py)
return
elif rev is None:
rev = 'Unable to determine SVN revision'
svn_info = get_svn_info()
# Wrap version, rev, and svn_info in str() to ensure that Python 2
# unicode literals aren't written, which will break things in Python 3
template_variables = {
'hook_function': function_name,
'name': name,
'version': str(version),
'vdate': str(vdate),
'svn_revision': str(rev),
'svn_full_info': str(svn_info),
'setup_datetime': datetime.datetime.now(),
}
# my_version is version.py for the stsci.distutils package.
# It can be None if we are called during the install of
# stsci.distutils; we are creating the version.py, so it was
# not available to import yet. If this is what is happening,
# we construct it specially.
if my_version is None :
if package == 'stsci.distutils' :
template_variables['stsci_distutils_version'] = version
else:
# It should never happen that version.py does not
# exist when we are installing any other package.
raise RuntimeError('Internal consistency error')
else :
template_variables['stsci_distutils_version'] = \
my_version.__version__
with open(version_py, 'w') as f:
f.write(VERSION_PY_TEMPLATE % template_variables)
def version_setup_hook(config):
"""Creates a Python module called version.py which contains these variables:
* ``__version__`` (the release version)
* ``__svn_revision__`` (the SVN revision info as returned by the ``svnversion``
command)
* ``__svn_full_info__`` (as returned by the ``svn info`` command)
* ``__setup_datetime__`` (the date and time that setup.py was last run).
* ``__vdate__`` (the release date)
These variables can be imported in the package's ``__init__.py`` for
degugging purposes. The version.py module will *only* be created in a
package that imports from the version module in its ``__init__.py``. It
should be noted that this is generally preferable to writing these
variables directly into ``__init__.py``, since this provides more control
and is less likely to unexpectedly break things in ``__init__.py``.
Config Usage::
[global]
setup-hooks = stsci.distutils.hooks.version_setup_hook
You should write exactly this in your package's ``__init__.py``::
from .version import *
"""
if is_display_option(ignore=['--version']):
return
name = config['metadata'].get('name')
version = config['metadata'].get('version', '0.0.0')
vdate = config['metadata'].get('vdate', 'unspecified')
package_dir = config.get('files', {}).get('packages_root', '')
packages = config.get('files', {}).get('packages', '')
packages = split_multiline(packages)
_version_hook(__name__ + '.version_setup_hook', package_dir, packages,
name, version, vdate)
def version_pre_command_hook(command_obj):
"""
.. deprecated:: 0.3
Use :func:`version_setup_hook` instead; it's generally safer to
check/update the version.py module on every setup.py run instead of on
specific commands.
This command hook creates an version.py file in each package that requires
it. This is by determining if the package's ``__init__.py`` tries to
import or import from the version module.
version.py will not be created in packages that don't use it. It should
only be used by the top-level package of the project.
"""
if is_display_option():
return
package_dir = command_obj.distribution.package_dir.get('', '.')
packages = command_obj.distribution.packages
name = command_obj.distribution.metadata.name
version = command_obj.distribution.metadata.version
_version_hook(__name__ + '.version_pre_command_hook',package_dir, packages,
name, version, vdate=None)
def version_post_command_hook(command_obj):
"""
.. deprecated:: 0.3
This hook was meant to complement :func:`version_pre_command_hook`,
also deprecated.
Cleans up a previously generated version.py in order to avoid
clutter.
Only removes the file if we're in an SVN working copy and the file is not
already under version control.
"""
package_dir = command_obj.distribution.package_dir.get('', '.')
packages = command_obj.distribution.packages
for package in packages:
clean_version_py(package_dir, package)
def numpy_extension_hook(command_obj):
"""A distutils2 pre-command hook for the build_ext command needed for
building extension modules that use NumPy.
To use this hook, add 'numpy' to the list of include_dirs in setup.cfg
section for an extension module. This hook will replace 'numpy' with the
necessary numpy header paths in the include_dirs option for that extension.
Note: Although this function uses numpy, stsci.distutils does not depend on
numpy. It is up to the distribution that uses this hook to require numpy
as a dependency.
Config Usage::
[extension=mypackage.extmod]
sources =
foo.c
bar.c
include_dirs = numpy
[build_ext]
pre-hook.numpy-extension = stsci.distutils.hooks.numpy_extension_hook
"""
command_name = command_obj.get_command_name()
if command_name != 'build_ext':
log.warn('%s is meant to be used with the build_ext command only; '
'it is not for use with the %s command.' %
(__name__, command_name))
try:
import numpy
except ImportError:
# It's virtually impossible to automatically install numpy through
# setuptools; I've tried. It's not pretty.
# Besides, we don't want users complaining that our software doesn't
# work just because numpy didn't build on their system.
sys.stderr.write('\n\nNumpy is required to build this package.\n'
'Please install Numpy on your system first.\n\n')
sys.exit(1)
includes = [numpy.get_include()]
#includes = [numpy.get_numarray_include(), numpy.get_include()]
for extension in command_obj.extensions:
if 'numpy' not in extension.include_dirs:
continue
idx = extension.include_dirs.index('numpy')
for inc in includes:
extension.include_dirs.insert(idx, inc)
extension.include_dirs.remove('numpy')
def glob_data_files(command_obj):
"""A pre-command hook for the install_data command allowing wildcard
patterns to be used in the data_files option.
Also ensures that data files with relative paths as their targets are
installed relative install_lib.
Config Usage::
[files]
data_files =
target_directory = source_directory/*.foo
other_target_directory = other_source_directory/*
[install_data]
pre-hook.glob-data-files = stsci.distutils.hooks.glob_data_files
"""
command_name = command_obj.get_command_name()
if command_name != 'install_data':
log.warn('%s is meant to be used with the install_data command only; '
'it is not for use with the %s command.' %
(__name__, command_name))
data_files = command_obj.data_files
for idx, val in enumerate(data_files[:]):
if isinstance(val, basestring):
# Support the rare, deprecated case where just a filename is given
filenames = glob.glob(val)
del data_files[idx]
data_files.extend(filenames)
continue
dest, filenames = val
filenames = sum((glob.glob(item) for item in filenames), [])
data_files[idx] = (dest, filenames)
# Ensure the correct install dir; this is the default behavior for
# installing with distribute, but when using
# --single-version-externally-managed we need to to tweak this
install_cmd = command_obj.get_finalized_command('install')
if command_obj.install_dir == install_cmd.install_data:
install_lib_cmd = command_obj.get_finalized_command('install_lib')
command_obj.install_dir = install_lib_cmd.install_dir
|