[pyjailhouse 2/2] pyjailhouse developer import tool

5 views
Skip to first unread message

Christopher Goldsworthy

unread,
May 19, 2018, 8:53:49 AM5/19/18
to jailho...@googlegroups.com, Christopher Goldsworthy
Add helper script and modify pyjailhouse's __init__.py file to allow a
developer to use either the installed version of pyjailhouse, or the version of
pyjailhouse located in the source tree.

Signed-off-by: Chris Goldsworthy <christopher...@outlook.com>
---
DEVREADME.md | 34 ++++++++++++++++++++++
devtools/pyjh_dev_mode | 53 +++++++++++++++++++++++++++++++++++
python_module/pyjailhouse/__init__.py | 41 +++++++++++++++++++++++++++
3 files changed, 128 insertions(+)
create mode 100644 DEVREADME.md
create mode 100755 devtools/pyjh_dev_mode

diff --git a/DEVREADME.md b/DEVREADME.md
new file mode 100644
index 0000000..f92e430
--- /dev/null
+++ b/DEVREADME.md
@@ -0,0 +1,34 @@
+# README For Jailhouse Developers
+
+## Import System for pyjailhouse
+
+The pyjailhouse module uses a import system which allows developers to have an
+installed version and a development version of pyjailhouse accessible (one at a
+time) to a jailhouse python script that imports pyjailhouse. This is provided as
+a convenience so that:
+1. Developers can test modifications to pyjailhouse without having to install it
+2. Users / developers can run jailhouse and use python scripts that import
+pyjailhouse without having to install jailhouse (i.e. without having to run
+`make install`)
+
+Effectively, **it's main use is to allow someone, when they choose to have it
+so, to make python import pyjailhouse (and any of its submodules / subpackages)
+from the jailhouse source tree**.
+
+# Usage:
+
+To make python import pyjailhouse from the source tree:
+1. Add the environment variable `PYJH_PARENT_DIR` - which should give the
+absolute path the directory **containing** pyjailhouse - to your .bashrc. This
+can be done using the below commands (the first command must be executed from
+[path_to_jailhouse]/python_module):
+
+`printf '\n\nPYJH_PARENT_DIR=%s && export PYJH_PARENT_DIR' "$(pwd)" >> ~/.bashrc`
+`source ~/.bashrc`
+
+2. Run `source [path_to_jailhouse]/devtools/pyjh_dev_mode`. This will append
+'(dev_mode): ' to your shell prompt. Python will now import pyjailhouse and any
+of its submodules / subpackages from the jailhouse source tree
+
+3. To have python import pyjailhouse from where it would normally import it
+from, simply run `source [path_to_jailhouse]/devtools/pyjh_dev_mode` again.
\ No newline at end of file
diff --git a/devtools/pyjh_dev_mode b/devtools/pyjh_dev_mode
new file mode 100755
index 0000000..f91001c
--- /dev/null
+++ b/devtools/pyjh_dev_mode
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# pyjailhouse, a python interface for the Jailhouse hypervisor
+#
+# Copyright (c) Christopher Goldsworthy, 2018
+#
+# Enables a developer to use either the source for pyjailhouse that's been
+# installed via pip, or the source for pyjailhouse in the jailhouse source
+# directory.
+#
+# When we want to import pyjailhouse from the source tree, we append
+# PYJH_PARENT_DIR to PYTHONPATH. When we no longer want this to be the case, we
+# simply undo this change. The __init__.py file of pyjailhouse decides what to
+# import, based off the presence of PYJH_PARENT_DIR in PYTHONPATH. Look in
+# jailhouse/python_module/pyjailhouse for an explanation of functionality
+
+if [ -z "$PYJH_PARENT_DIR" ]; then
+cat << heredoc
+In order for this script to work, you need to set the environment variable
+PYJH_PARENT_DIR, which should give the path to the parent directory of
+pyjailhouse (jailhouse/python_module). Run the below from said parent directory:
+
+printf '\n\nPYJH_PARENT_DIR=%s && export PYJH_PARENT_DIR' "\$(pwd)" >> ~/.bashrc && source ~/.bashrc
+heredoc
+ return
+fi
+
+if [[ "$PYTHONPATH" != *"$PYJH_PARENT_DIR"* ]]; then
+ # Add PYJH_PARENT_DIR to PYTHONPATH so that when pyjailhouse/__init__.py
+ # runs, the version of pyjailhouse in the jailhouse source tree gets
+ # imported, instead of the installed version
+
+ # Modify python path to include PYJH_PARENT_DIR
+ PYTHONPATH_SAVE="${PYTHONPATH}"
+ PYTHONPATH="${PYTHONPATH}:${PYJH_PARENT_DIR}"
+ export PYTHONPATH
+
+ # Change shell prompt
+ PS1_SAVE="$PS1"
+ PS1="${PS1}(dev_mode): "
+else
+ # Remove PYJH_PARENT_DIR from PYTHONPATH so that when
+ # pyjailhouse/__init__.py runs, the installed version of pyjailhouse gets
+ # installed, instead of the version in the source tree
+
+ # Undo changes made above
+ PYTHONPATH="${PYTHONPATH_SAVE}"
+ export PYTHONPATH
+ unset PYTHONPATH_SAVE
+
+ PS1="$PS1_SAVE"
+ unset PS1_SAVE
+fi
\ No newline at end of file
diff --git a/python_module/pyjailhouse/__init__.py b/python_module/pyjailhouse/__init__.py
index e69de29..c46ce70 100644
--- a/python_module/pyjailhouse/__init__.py
+++ b/python_module/pyjailhouse/__init__.py
@@ -0,0 +1,41 @@
+
+# pyjailhouse, a python interface for the Jailhouse Hypervisor
+#
+# Copyright (c) Christopher Goldsworthy, 2018
+#
+# Checks to see if environment variable PYJH_PARENT_DIR is contained
+# (stringwise) in the environment variable PYTHONPATH. If so, import
+# pyjailhouse's submodules / subpackages from the source tree by setting
+# __path__ to be the pyjailhouse directory in the source tree. Otherwise (or
+# if PYJH_PARENT_DIR has not been set at all), let python import the
+# submodules / subpackages from the directory containing this copy of
+# __init__.py by making no modifications to __path__.
+#
+# There are two subtleties worth mentioning here. Firstly, if jailhouse hasn't
+# been installed (i.e. the only copy of pyjailhouse is in the source tree) and
+# PYTHONPATH contains PYJH_PARENT_DIR (i.e. the user has sourced
+# jailhouse/devtools/pyjh_dev_mode), then __init__.py will run out of the
+# pyjailhouse source directory (since there's only one copy of __init__.py).
+# __init__.py will also set __path__ to the directory containing itself, which
+# has no effect, since this is what python would have searched through
+# during the import process anyways.
+#
+# Secondly, when pyjailhouse is installed, two copies of this file exist, one
+# in the installation directory and one in the directory pip installs it in. If
+# pyjh_dev_mode hasn't been sourced, then the installed version of __init__.py
+# will be the only one to run. It pyjh_dev_mode has been sourced, either
+# __init__.py could run. In either case though, we reach the desired result of
+# importing out of the source tree (by setting __path__ as we do).
+#
+# For an overview of how __path__ is being used here, refer to
+# Chapter 5 (The import system) of any Python 3.* Language Reference
+
+import os
+import os.path
+
+try:
+ PYJH_PARENT_DIR = os.environ["PYJH_PARENT_DIR"]
+ if PYJH_PARENT_DIR in os.environ["PYTHONPATH"]:
+ __path__ = [os.path.join(PYJH_PARENT_DIR, "pyjailhouse")]
+except KeyError: # User hasn't exported PYJH_PARENT_DIR, import module as is
+ pass
--
2.7.4

Christopher Goldsworthy

unread,
May 19, 2018, 8:56:49 AM5/19/18
to jailho...@googlegroups.com, Christopher Goldsworthy

Jan Kiszka

unread,
May 19, 2018, 10:59:02 AM5/19/18
to Christopher Goldsworthy, jailho...@googlegroups.com
I'm sure you dug much deeper into the nasty details than I. So I guess
you can quickly explain to me (and maybe also in the commit) why
something along this line does not work with Python:

- have some boilerplate code in each in-tree user (tools/jailhouse-*) of
the module that prepends the in-tree module source code to __path__
before even importing anything from pyjailhouse

- patch out that boilerplate code (or dynamically disable it) when the
tool is properly installed

- ideally, leave pyjailhouse/__init__.py without any special logic

If something like that would work, the developer just had to call the
jailhouse tool under development from the source code path, rather than
switching the mode via the helper script.

Thanks,
Jan
Reply all
Reply to author
Forward
0 new messages