Skip to content
This repository has been archived by the owner on Jul 19, 2023. It is now read-only.

Commit

Permalink
Merge pull request #112 from keisukefukuda/fix-misc
Browse files Browse the repository at this point in the history
misc fix
  • Loading branch information
keisukefukuda committed Mar 8, 2019
2 parents 24e529c + c6a4d82 commit 152f828
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 31 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ versions
*.pyc
pylib
dist
.idea
*.egg-info
.pytest_cache

4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ sudo: false

dist: trusty

cache:
directories:
- /home/travis/mpi

env:
- PIP_VER=19.0.3 TEST_SHELL_CMD=bash LANG=C
- PIP_VER=18.0 TEST_SHELL_CMD=zsh LANG=C
Expand Down
23 changes: 23 additions & 0 deletions mpienv/command/describe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# coding: utf-8

import argparse

from mpienv import mpienv


parser = argparse.ArgumentParser(
prog='mpienv describe',
description='Describe a registered MPI')
parser.add_argument('name', metavar='name', type=str,
help='Name of an MPI installation')


def main():
args = parser.parse_args()

# Create a link
mpienv.describe(args.name)


if __name__ == "__main__":
main()
21 changes: 21 additions & 0 deletions mpienv/command/restore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# coding: utf-8

import argparse

from mpienv import mpienv


parser = argparse.ArgumentParser(
prog='mpienv refresh',
description='Restore the status')


def main():
args = parser.parse_args() # NOQA

# Create a link
mpienv.restore()


if __name__ == "__main__":
main()
18 changes: 16 additions & 2 deletions mpienv/command/use.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,33 @@
import argparse

from mpienv import mpienv
import sys

parser = argparse.ArgumentParser(
prog='mpienv use', description='Set the specific MPI environment.')
parser.add_argument('-p', '--mpi4py', action="store_true",
dest="mpi4py", default=False,
help="Also switch mpi4py library")
help="Activate mpi4py library for "
"the current python (default)")
parser.add_argument('--no-mpi4py', action='store_true',
dest='no_mpi4py', default=False,
help="Do not activate mpi4py library")
parser.add_argument('name', type=str,
help="MPI name to use")


def main():
args = parser.parse_args()
mpienv.use(args.name, mpi4py=args.mpi4py)

if args.mpi4py and args.no_mpi4py:
sys.stderr.write("mpienv: Error: both of --mpi4py "
"and --no-mpi4py are specified.")
exit(1)

if args.mpi4py:
sys.stderr.write("mpienv: Info: --mpi4py is ON by default.\n")

mpienv.use(args.name, no_mpi4py=args.no_mpi4py)


if __name__ == "__main__":
Expand Down
43 changes: 35 additions & 8 deletions mpienv/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,18 @@ def is_installed(self, mpiexec):
return None

def get_current_name(self):
try:
return next(name for name, mpi in self.items() if mpi.is_active)
except StopIteration:
raise UnknownMPI()
if 'DEFAULT' in self.config2 and 'active' in self.config2['DEFAULT']:
name = self.config2['DEFAULT']['active']

# Check
if not self.get_mpi_from_name(name).is_active:
sys.stderr.write("mpienv: Error: Internal status is "
"inconsistent. Please hit 'mpienv use' "
"command to refresh the status.\n")
exit(1)
return name
else:
raise RuntimeError("No MPI is activated.")

def add(self, target, name=None):
# `target` is expected to be an mpiexec command or its prefix
Expand Down Expand Up @@ -253,7 +261,7 @@ def add(self, target, name=None):
exit(-1)

if name in self.config2:
sys.stderr.write("{} is already registered.".format(name))
sys.stderr.write("{} is already registered.\n".format(name))
else:
self.config2.add_section(name)
self.config2[name]['name'] = name
Expand Down Expand Up @@ -294,7 +302,7 @@ def rename(self, name_from, name_to):
if mpi4py.is_installed():
mpi4py.rename(name_to)

def use(self, name, mpi4py=False):
def use(self, name, no_mpi4py=False):
mpi = self.get_mpi_from_name(name)

if isinstance(mpi, BrokenMPI):
Expand All @@ -310,13 +318,32 @@ def use(self, name, mpi4py=False):
"".format(name))
exit(-1)

mpi.use(name, mpi4py=mpi4py)
mpi.use(name, no_mpi4py=no_mpi4py)

def exec_(self, cmds, **kwargs):
name = self.get_current_name()
try:
name = self.get_current_name()
except RuntimeError:
sys.stderr.write("mpienv: Error: No MPI is currently activated.\n")
mpi = self.get_mpi_from_name(name)
mpi.exec_(cmds, **kwargs)

def restore(self):
if 'DEFAULT' in self.config2:
try:
mpi_name = self.config2['DEFAULT']['active']
if 'mpi4py' in self.config2['DEFAULT']:
mpi4py = self.config2['DEFAULT'].getboolean('mpi4py')
else:
mpi4py = True
except KeyError:
return
self.use(mpi_name, mpi4py)

def describe(self, name):
mpi = self.get_mpi_from_name(name)
mpi.describe()


_root_dir = (os.environ.get("MPIENV_ROOT", None) or
os.path.join(os.path.expanduser('~'), '.mpienv'))
Expand Down
38 changes: 29 additions & 9 deletions mpienv/mpibase.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ def exec_(self, cmds, dry_run=False, verbose=False):
print("tempfile = {}".format(tempfile))
print("hosts = {}".format(remote_hosts))

# Generate a proxy shell script that runs user programs
self._generate_exec_script(tempfile, cmds)

# Copy script file
Expand All @@ -333,10 +334,19 @@ def exec_(self, cmds, dry_run=False, verbose=False):
check_call(['scp', tempfile, '{}:{}'.format(host, tempfile)])

# Run the mpiexec command
args, _ = split_mpi_user_prog(cmds)
mpi_args, user_args = split_mpi_user_prog(cmds)

# Warn if user tries to run python program while --mpi4py is not active
if user_args[0].startswith('python'):
if not mpienv.mpienv.config2['DEFAULT'].getboolean('mpi4py'):
sys.stderr.write("mpienv: Warn: It seems that you are trying"
" to run a pythohn progrma, but mpi4py is not"
" ")

# Execute mpiexec
mpiexec = self.mpiexec
if dry_run:
print(' '.join([mpiexec] + args + [tempfile]))
print(' '.join([mpiexec] + mpi_args + [tempfile]))
if verbose:
print("")
print(tempfile)
Expand All @@ -345,7 +355,7 @@ def exec_(self, cmds, dry_run=False, verbose=False):
else:
sys.stdout.flush()
sys.stderr.flush()
os.execv(mpiexec, [mpiexec] + args + [tempfile])
os.execv(mpiexec, [mpiexec] + mpi_args + [tempfile])

def run_cmd(self, cmd, extra_envs):
envs = os.environ.copy()
Expand Down Expand Up @@ -376,25 +386,25 @@ def _generate_path(self):
return env_path

def _generate_ldlib(self):
env_ldlib = os.environ.get('LIBRARY_PATH', '').split(':')
env_ldlib = os.environ.get('LD_LIBRARY_PATH', '').split(':')

# Remove all directory that contains 'mpiexec'
for dir_name in ['lib', 'lib64']:
lib_dir = os.path.join(self.prefix, dir_name)
if os.path.exists(lib_dir):
# Remove if lib_is already a part of LD_LIBRARY_PATH
# to avoid LD_LIBRARY_PATH is too long.
if lib_dir in env_ldlib:
env_ldlib.remove(lib_dir)
env_ldlib = [lib_dir] + env_ldlib

return env_ldlib

def use(self, name, mpi4py=False):
def use(self, name, no_mpi4py=False):
# Check if the specified `name` is the same as the current one
try:
cur_name = mpienv.mpienv.config2['DEFAULT']['name']
cur_mpi4py = mpienv.mpienv.config2.getboolean('DEFAULT', 'mpi4py')
if cur_name == name and cur_mpi4py == mpi4py:
if cur_name == name and cur_mpi4py == (not no_mpi4py):
return
except KeyError:
pass
Expand All @@ -403,7 +413,7 @@ def use(self, name, mpi4py=False):
env_ldlib = self._generate_ldlib()

mpienv.mpienv.config2['DEFAULT']['active'] = name
mpienv.mpienv.config2['DEFAULT']['mpi4py'] = str(mpi4py)
mpienv.mpienv.config2['DEFAULT']['mpi4py'] = str(not no_mpi4py)
mpienv.mpienv.config_save()

print('export PATH={}'.format(':'.join(env_path)))
Expand All @@ -414,7 +424,7 @@ def use(self, name, mpi4py=False):
env['LD_LIBRARY_PATH'] = ':'.join(env_ldlib)

py = MPI4Py(self._conf, name)
if mpi4py:
if not no_mpi4py:
if not py.is_installed():
py.install(env)
py.use()
Expand All @@ -435,3 +445,13 @@ def remove(self):
shutil.rmtree(self.prefix)
else:
os.remove(os.path.join(self._conf['mpi_dir'], self.name))

def describe(self):
print("Name : {}".format(self.name))
print("Type : {}".format(self.type_))
print("Version : {}".format(self.version))
print("Path : {}".format(self.prefix))
self._describe()

def _describe(self):
pass
20 changes: 19 additions & 1 deletion mpienv/mpienv_init.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import sys

_template = """
export MPIENV_ROOT="$HOME/.mpienv"
if [ -z "${MPIENV_ROOT:-}" ]; then
export MPIENV_ROOT="$HOME/.mpienv"
fi
PYTHON=__SYS_EXECUTABLE__
if [ -z "${MPIENV_VERSIONS_DIR:-}" ]; then
Expand Down Expand Up @@ -39,12 +41,26 @@
$PYTHON -m mpienv.command.add $*
}
;;
"restore" )
{
eval "$(env PYTHONPATH=$MPIENV_ROOT:${PYTHONPATH:-} $PYTHON -m mpienv.command.restore $*)" # NOQA
if [ -z "${BASH_VERSION:-}" -a ! -z "${ZSH_VERSION:-}" ]; then
rehash
fi
}
;;
"rm" )
{
env PYTHONPATH=$MPIENV_ROOT:${PYTHONPATH:-} \
$PYTHON -m mpienv.command.rm "$@"
}
;;
"describe" )
{
env PYTHONPATH=$MPIENV_ROOT:${PYTHONPATH:-} \
$PYTHON -m mpienv.command.describe "$@"
}
;;
"rename" )
{
env PYTHONPATH=$MPIENV_ROOT:${PYTHONPATH:-} \
Expand Down Expand Up @@ -92,6 +108,8 @@
;;
esac
}
mpienv restore
"""


Expand Down
2 changes: 1 addition & 1 deletion mpienv/py.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def clear(self):
if newpath == "":
print("unset PYTHONPATH;")
else:
sys.stderr.write("export PYTHONPATH={}\n".format(newpath))
print("export PYTHONPATH={}\n".format(newpath))

def rm(self):
if os.path.exists(self._pylib_dir):
Expand Down
15 changes: 9 additions & 6 deletions tests/test_main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ setUp() {
export MPIENV_ROOT=$TMPDIR/mpienv/
rm -rf $MPIENV_ROOT |:
mkdir -p $MPIENV_ROOT
rm -rf ~/.mpienv # Regression test. MPIENV_ROOT is set to /tmp/mpienv in this test script.
}

tearDown() {
Expand Down Expand Up @@ -191,6 +192,7 @@ test_openmpi_info() {
test_1mpi() {
# mpienv list
mpienv autodiscover -q --add ${MPI_PREFIX}
rm -rf ~/.mpienv # Regression test. MPIENV_ROOT is set to /tmp/mpienv in this test script.

mpienv list | grep -q mpich-${MPICH_VER}
assertTrue "$?"
Expand Down Expand Up @@ -320,25 +322,26 @@ test_mpi4py_clear_pypath() {
assertNull "${PYTHONPATH:-}"

mpienv use ${MPICH}
assertNull "${PYTHONPATH:-}"
assertNotNull "PYTHONPATH must be set for ${MPICH}" "${PYTHONPATH:-}"

mpienv use --mpi4py ${MPICH}
assertNotNull "PYTHONPATH must be set for ${MPICH}" "${PYTHONPATH:-}"

mpienv use ${MPICH}
mpienv use --no-mpi4py ${MPICH}
assertNull "PYTHONPATH must be NULL" "${PYTHONPATH:-}"

mpienv use --mpi4py ${MPICH}
echo "$PYTHONPATH" | grep ${MPICH}
assertEquals "PYTHONPATH must contain ${MPICH}" 0 $?

mpienv rename "${MPICH}" mpix
mpienv use mpix
assertNull "PYTHONPATH must be NULL" "${PYTHONPATH:-}"

mpienv use --mpi4py mpix
mpienv use mpix
echo "$PYTHONPATH" | grep mpix
assertEquals "PYTHONPATH must contain mpix" 0 $?

mpienv use --no-mpi4py mpix
assertNull "PYTHONPATH must be NULL" "${PYTHONPATH:-}"
}

test_mpi4py() {
Expand Down Expand Up @@ -410,7 +413,7 @@ test_reg_issue10(){
mpienv use --mpi4py ${MPICH} # this command should install mpi4py to mpich-3.2
mpienv rename ${MPICH} mpix # The mpi4py module should be taken over to 'mpix'

OUT=$(mpienv use --mpi4py mpix 2>&1) # this command should NOT intall mpi4py again
OUT=$(mpienv use mpix 2>&1) # this command should NOT intall mpi4py again

# If the `use` command does not run `pip install mpi4py`,
# which is a correct behavior, E-S should be < 1 [s].
Expand Down

0 comments on commit 152f828

Please sign in to comment.