Python Development¶
Qip provide a few features to ease the development process.
Editable mode¶
Qip provides an editable mode to allow for rapid development when developing a Python package:
>>> qip install -e .
See also
Let’s clone the popular Pystache repository to demonstrate this feature:
>>> git clone https://github.com/defunkt/pystache.git
>>> cd ./pystache
>>> qip install -e .
The pystache
definition will ensure that the install-location value will target the cloned repository:
{
"identifier": "pystache",
"version": "0.5.4",
"namespace": "library",
"description": "Mustache for Python",
"command": {
"pystache": "python -m pystache.commands.render",
"pystache-test": "python -m pystache.commands.test"
},
"environ": {
"PYTHONPATH": "${INSTALL_LOCATION}:${PYTHONPATH}"
},
"variants": [
{
"identifier": "3.8",
"install-location": "/path/to/pystache/",
"requirements": [
"python >= 3.8, < 3.9"
]
}
]
}
It is then possible to execute the following command:
>>> wiz -add /tmp/qip/definitions run pystache -- 'Hello {{world}}' '{"world": "everybody"}'
info: Start command: python -m pystache.commands.render 'Hello {{world}}' '{"world": "everybody"}'
Hello everybody
You can modify the pystache/commands/render.py
file to print a different
output and ensure that it works as expected:
diff --git a/pystache/commands/render.py b/pystache/commands/render.py
index 1a9c309..9738c5e 100644
--- a/pystache/commands/render.py
+++ b/pystache/commands/render.py
@@ -88,7 +88,7 @@ def main(sys_argv=sys.argv):
context = json.loads(context)
rendered = renderer.render(template, context)
- print rendered
+ print "test " + rendered
The command will then return:
>>> wiz -add /tmp/qip/definitions run pystache -- 'Hello {{world}}' '{"world": "everybody"}'
info: Start command: python -m pystache.commands.render 'Hello {{world}}' '{"world": "everybody"}'
test Hello everybody
Optional dependencies¶
Qip supports extra keywords provided in the request. Many Python packages use this installation feature, like Gunicorn.
>>> qip install gunicorn[gevent]
When using extra keywords, the nature of the package installed is fundamentally modified. Not only does it change the dependencies, but it could also change the Entry-Points created.
See also
To prevent name clashes, the Wiz definition extracted will include the list of sorted extra keywords used within its identifier:
{
"identifier": "gunicorn-event",
...
}
Custom Wiz definition¶
A default Wiz definition will be created for each Python packages to install. It will contain:
- identifier based of the project name.
- version based on the package version.
- description based on the package description.
- commands based on entry points defined in
setup.py
. - requirements based on package dependencies.
- install-location based on relative library path.
It is possible to add a custom definition within the repository to extend this
Wiz definition. The custom definition should be included in the source
code under package_data/wiz.json
.
Let’s use again the Pystache repository to demonstrate this feature:
>>> git clone https://github.com/defunkt/pystache.git
>>> cd ./pystache
Add the following definition in pystache/package_data/wiz.json
{
"command": {
"say_hello": "python -m pystache.commands.render 'Hello {{world}}' '{\"world\": \"everybody\"}'"
}
}
Now install the definition as follows:
>>> qip install .
It is then possible to execute the following command:
>>> wiz -add /tmp/qip/definitions run say_hello
info: Start command: python -m pystache.commands.render 'Hello {{world}}' '{"world": "everybody"}'
Hello everybody
Using a custom definition could be particularly helpful when a Python package depends on a non-Python library.
Note
It is also possible to add optional custom definition matching
extra keywords provided in the request.
For instance, if a non-Python library must be set as a dependency when the
“gevent” keyword is passed when installing the
Gunicorn
library, a targeted definition can be set in
gunicorn/package_data/wiz-gevent.json
.
Working with DCCs¶
When writing a Python plugin for a Digital content creation tool, a custom Wiz definition should be used to ease the development and deployment process.
Here are a few usage examples:
{
"identifier": "foo",
"namespace": "maya",
"environ": {
"MAYA_PLUG_IN_PATH": "${INSTALL_LOCATION}/foo/package_data/maya/plugin:${MAYA_PLUG_IN_PATH}",
"MAYA_SCRIPT_PATH": "${INSTALL_LOCATION}/foo/package_data/maya/script/mel:${MAYA_SCRIPT_PATH}",
"PYTHONPATH": "${INSTALL_LOCATION}/foo/package_data/maya/script/python:${PYTHONPATH}"
},
"requirements": [
"maya"
]
}
{
"identifier": "foo",
"namespace": "flame",
"environ": {
"DL_PYTHON_HOOK_PATH": "${INSTALL_LOCATION}/foo/package_data/python:${DL_PYTHON_HOOK_PATH}"
},
"requirements": [
"flame"
]
}
{
"identifier": "foo",
"namespace": "nuke",
"environ": {
"NUKE_PATH": "${INSTALL_LOCATION}/foo/package_data/nuke:${NUKE_PATH}"
},
"requirements": [
"nuke"
]
}
{
"identifier": "foo",
"namespace": "houdini",
"environ": {
"HOUDINI_PATH": "${INSTALL_LOCATION}/foo/package_data/houdini:${HOUDINI_PATH}"
},
"requirements": [
"houdini"
]
}
{
"identifier": "foo",
"namespace": "rv",
"environ": {
"RV_SUPPORT_PATH": "${INSTALL_LOCATION}/foo/package_data/rv:${RV_SUPPORT_PATH}"
},
"requirements": [
"rv"
]
}