|
|
# encoding: utf-8
|
|
|
"""
|
|
|
Utilities for getting information about IPython and the system it's running in.
|
|
|
"""
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Copyright (C) 2008-2009 The IPython Development Team
|
|
|
#
|
|
|
# Distributed under the terms of the BSD License. The full license is in
|
|
|
# the file COPYING, distributed as part of this software.
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Imports
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
import os
|
|
|
import platform
|
|
|
import pprint
|
|
|
import sys
|
|
|
import subprocess
|
|
|
|
|
|
from ConfigParser import ConfigParser
|
|
|
|
|
|
from IPython.core import release
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Globals
|
|
|
#-----------------------------------------------------------------------------
|
|
|
COMMIT_INFO_FNAME = '.git_commit_info.ini'
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Code
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
def pkg_commit_hash(pkg_path):
|
|
|
"""Get short form of commit hash given directory `pkg_path`
|
|
|
|
|
|
There should be a file called 'COMMIT_INFO.txt' in `pkg_path`. This is a
|
|
|
file in INI file format, with at least one section: ``commit hash``, and two
|
|
|
variables ``archive_subst_hash`` and ``install_hash``. The first has a
|
|
|
substitution pattern in it which may have been filled by the execution of
|
|
|
``git archive`` if this is an archive generated that way. The second is
|
|
|
filled in by the installation, if the installation is from a git archive.
|
|
|
|
|
|
We get the commit hash from (in order of preference):
|
|
|
|
|
|
* A substituted value in ``archive_subst_hash``
|
|
|
* A written commit hash value in ``install_hash`
|
|
|
* git output, if we are in a git repository
|
|
|
|
|
|
If all these fail, we return a not-found placeholder tuple
|
|
|
|
|
|
Parameters
|
|
|
----------
|
|
|
pkg_path : str
|
|
|
directory containing package
|
|
|
|
|
|
Returns
|
|
|
-------
|
|
|
hash_from : str
|
|
|
Where we got the hash from - description
|
|
|
hash_str : str
|
|
|
short form of hash
|
|
|
"""
|
|
|
# Try and get commit from written commit text file
|
|
|
pth = os.path.join(pkg_path, COMMIT_INFO_FNAME)
|
|
|
if not os.path.isfile(pth):
|
|
|
raise IOError('Missing commit info file %s' % pth)
|
|
|
cfg_parser = ConfigParser()
|
|
|
cfg_parser.read(pth)
|
|
|
archive_subst = cfg_parser.get('commit hash', 'archive_subst_hash')
|
|
|
if not archive_subst.startswith('$Format'): # it has been substituted
|
|
|
return 'archive substitution', archive_subst
|
|
|
install_subst = cfg_parser.get('commit hash', 'install_hash')
|
|
|
if install_subst != '':
|
|
|
return 'installation', install_subst
|
|
|
# maybe we are in a repository
|
|
|
proc = subprocess.Popen('git rev-parse --short HEAD',
|
|
|
stdout=subprocess.PIPE,
|
|
|
stderr=subprocess.PIPE,
|
|
|
cwd=pkg_path, shell=True)
|
|
|
repo_commit, _ = proc.communicate()
|
|
|
if repo_commit:
|
|
|
return 'repository', repo_commit.strip()
|
|
|
return '(none found)', '<not found>'
|
|
|
|
|
|
|
|
|
def pkg_info(pkg_path):
|
|
|
"""Return dict describing the context of this package
|
|
|
|
|
|
Parameters
|
|
|
----------
|
|
|
pkg_path : str
|
|
|
path containing __init__.py for package
|
|
|
|
|
|
Returns
|
|
|
-------
|
|
|
context : dict
|
|
|
with named parameters of interest
|
|
|
"""
|
|
|
src, hsh = pkg_commit_hash(pkg_path)
|
|
|
return dict(
|
|
|
ipython_version=release.version,
|
|
|
ipython_path=pkg_path,
|
|
|
commit_source=src,
|
|
|
commit_hash=hsh,
|
|
|
sys_version=sys.version,
|
|
|
sys_executable=sys.executable,
|
|
|
sys_platform=sys.platform,
|
|
|
platform=platform.platform(),
|
|
|
os_name=os.name,
|
|
|
)
|
|
|
|
|
|
|
|
|
def sys_info():
|
|
|
"""Return useful information about IPython and the system, as a string.
|
|
|
|
|
|
Example
|
|
|
-------
|
|
|
In [2]: print sys_info()
|
|
|
{'commit_hash': '144fdae', # random
|
|
|
'commit_source': 'repository',
|
|
|
'ipython_path': '/home/fperez/usr/lib/python2.6/site-packages/IPython',
|
|
|
'ipython_version': '0.11.dev',
|
|
|
'os_name': 'posix',
|
|
|
'platform': 'Linux-2.6.35-22-generic-i686-with-Ubuntu-10.10-maverick',
|
|
|
'sys_executable': '/usr/bin/python',
|
|
|
'sys_platform': 'linux2',
|
|
|
'sys_version': '2.6.6 (r266:84292, Sep 15 2010, 15:52:39) \\n[GCC 4.4.5]'}
|
|
|
"""
|
|
|
p = os.path
|
|
|
path = p.dirname(p.abspath(p.join(__file__, '..')))
|
|
|
return pprint.pformat(pkg_info(path))
|
|
|
|
|
|
|
|
|
def _num_cpus_unix():
|
|
|
"""Return the number of active CPUs on a Unix system."""
|
|
|
return os.sysconf("SC_NPROCESSORS_ONLN")
|
|
|
|
|
|
|
|
|
def _num_cpus_darwin():
|
|
|
"""Return the number of active CPUs on a Darwin system."""
|
|
|
p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
|
|
|
return p.stdout.read()
|
|
|
|
|
|
|
|
|
def _num_cpus_windows():
|
|
|
"""Return the number of active CPUs on a Windows system."""
|
|
|
return os.environ.get("NUMBER_OF_PROCESSORS")
|
|
|
|
|
|
|
|
|
def num_cpus():
|
|
|
"""Return the effective number of CPUs in the system as an integer.
|
|
|
|
|
|
This cross-platform function makes an attempt at finding the total number of
|
|
|
available CPUs in the system, as returned by various underlying system and
|
|
|
python calls.
|
|
|
|
|
|
If it can't find a sensible answer, it returns 1 (though an error *may* make
|
|
|
it return a large positive number that's actually incorrect).
|
|
|
"""
|
|
|
|
|
|
# Many thanks to the Parallel Python project (http://www.parallelpython.com)
|
|
|
# for the names of the keys we needed to look up for this function. This
|
|
|
# code was inspired by their equivalent function.
|
|
|
|
|
|
ncpufuncs = {'Linux':_num_cpus_unix,
|
|
|
'Darwin':_num_cpus_darwin,
|
|
|
'Windows':_num_cpus_windows,
|
|
|
# On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
|
|
|
# See http://bugs.python.org/issue1082 for details.
|
|
|
'Microsoft':_num_cpus_windows,
|
|
|
}
|
|
|
|
|
|
ncpufunc = ncpufuncs.get(platform.system(),
|
|
|
# default to unix version (Solaris, AIX, etc)
|
|
|
_num_cpus_unix)
|
|
|
|
|
|
try:
|
|
|
ncpus = max(1,int(ncpufunc()))
|
|
|
except:
|
|
|
ncpus = 1
|
|
|
return ncpus
|
|
|
|
|
|
|