Using IPython with Plone

Are there some instructions how to use Jupyter (or IPython) with Plone 5.2.6 and get the instance environment?

I've tried it with the old instructions for Plone 4 but I'm not able to get the instance.

Maybe share what you have tried and the errors you get?

I assume, Plone 6 with the pip based install approach is very easy to wire in. But I never tried it nor do I have time at the moment. But reports are welcome!

I've added the following to /home/Plone-5.2.6/zeocluster/develop.cfg:

[buildout]
...
parts +=
...
    ipzope
...
[ipzope]
recipe = zc.recipe.egg
eggs =
    ipython
    ${client2:eggs}
initialization =
    import sys, os
    os.environ["INSTANCE_HOME"] = "${client2:location}"
    sys.argv[1:1] = "--profile=zope".split()
scripts = ipython=ipzope
...
[versions]
ipython = 6.5.0

Newer versions of ipython (8x or 7x) cannot be installed due to version requirements:

  • Error: The requirement ('prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0') is not allowed by your [versions] constraint (1.0.18) for ipython 8x
  • Error: The requirement ('prompt-toolkit<2.1.0,>=2.0.0') is not allowed by your [versions] constraint (1.0.18) for ipython7x

With ipython = 6.5.0 in develop.cfg call:

sudo -u buildout_user /home/Plone-5.2.6/zeocluster/bin/buildout -c /home/Plone-5.2.6/zeocluster/develop.cfg

I run the following to check if the zeoserver and the client2 are running and app is bound and the plone.api can be imported:

$ sudo /home/Plone-5.2.6/zeocluster/bin/plonectl start zeoserver`
$ sudo /home/Plone-5.2.6/zeocluster/bin/client2 debug
Starting debugger (the name "app" is bound to the top-level Zope object) 
>>> app
<Application at >
>>> plone = app.get('Plone')
>>> plone
<PloneSite at /Plone>
>>> from zope.component.hooks import setSite
>>> setSite(plone)
>>> from plone import api
>>> api.portal.get()
<PloneSite at /Plone>

But when trying it from ipzope it doesn't work:

$ sudo /home/Plone-5.2.6/zeocluster/bin/ipzope
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.

IPython profile: zope

In [1]: app
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-8d494114ce46> in <module>()
----> 1 app

NameError: name 'app' is not defined

In [2]: from plone import api
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/usr/lib/python3.9/codeop.py in __call__(self, source, filename, symbol)
    141
    142     def __call__(self, source, filename, symbol):
--> 143         codeob = compile(source, filename, symbol, self.flags, True)
    144         for feature in _features:
    145             if codeob.co_flags & feature.compiler_flag:

TypeError: required field "type_ignores" missing from Module

I have tried to modify the old https://github.com/collective/dotipython/archive/master.zip to run with Python 3 (basically print and StringType issues. But no success.

I have tried to understand how client2 debug, client2/bin/interpreter etc. work. But I get lost

Some hints, how to get IPython working with Plone 5?

What would the idea with using Jupyter with Plone? Connect directly to the ZODB, having a nicer prompt to interact with the objects? What are the scenarios where this is worth the trouble?

@tiberiuichim: Just to clarify possible misunderstandings. Probably I've asked my question in the wrong topic. sorry:

I'm trying to get just plain IPython running with Plone 5.2.6.

My main scenario is to access and interact with Plone 5 in servers without Desktop mainly via terminal. IPython offers a valuable interaction with the objects.

1 Like

what about:
from IPython import embed; embed()?

@yurj: I did try this too. But there are also problems:

from plone import api
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/usr/lib/python3.9/codeop.py in __call__(self, source, filename, symbol)
    141
    142     def __call__(self, source, filename, symbol):
--> 143         codeob = compile(source, filename, symbol, self.flags, True)
    144         for feature in _features:
    145             if codeob.co_flags & feature.compiler_flag:

TypeError: required field "type_ignores" missing from Module

It was a versions problem.

One of the problems (missing from Module) was due to IPython's incompatibility wiht Python versions after 3.3:

Beginning with version 6.0, IPython stopped supporting compatibility with Python versions lower than 3.3 including all versions of Python 2.7. (https://ipython.readthedocs.io/en/stable/whatsnew/version8.html)

The other problem was that IPython versions 8x or 7x cannot be installed due to version requirements on prompt-toolkit.

  • with IPython 8x: Error: The requirement ('prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0') is not allowed by your [versions] constraint (1.0.18)
  • with IPython 7x: Error: The requirement ('prompt-toolkit<2.1.0,>=2.0.0') is not allowed by your [versions] constraint (1.0.18)

With following versions pinned it works fine:

  • ipython = 8.0.1 and prompt-toolkit = 3.0.24
  • ipython = 8.0.1 and prompt-toolkit = 2.0.10
  • ipython = 7.31 and prompt-toolkit = 3.0.24

I document here the needed steps to work with IPython 8.0.1 in Plone 5.2.6:

# add ipython to eggs
sudo sed -i '/^eggs +=$/a \ \ \ \ ipython' /home/Plone-5.2.6/zeocluster/develop.cfg
# pin the versions
cat <<'EOF' | sudo tee -a /home/Plone-5.2.6/zeocluster/develop.cfg
[versions]
ipython = 8.0.1
prompt-toolkit = 3.0.24
EOF
# run buildout
sudo -u buildout_user \
    /home/Plone-5.2.6/zeocluster/bin/buildout \
    -c /home/Plone-5.2.6/zeocluster/develop.cfg
# start zeoserver
sudo /home/Plone-5.2.6/zeocluster/bin/plonectl start zeoserver
# start client2 debug
sudo /home/Plone-5.2.6/zeocluster/bin/client2 debug

The debugger starts as follows

Starting debugger (the name "app" is bound to the top-level Zope object)

check it

>>> app
<Application at >

Embed IPython

>>> from IPython import embed; embed()

and voilà

Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.0.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: plone = app.get("Plone")
   ...: plone
Out[1]: <PloneSite at /Plone>

In [2]: from zope.component.hooks import setSite
   ...: setSite(plone)
   ...: from plone import api
   ...: portal = api.portal.get()
   ...: portal
Out[2]: <PloneSite at /Plone>
3 Likes

sounds like we should change the title of your thread branch then, to "Anyone using IPython with Plone"? @mekell

@tkimnguyen: That's a good idea. Thank you.
If possible rename to Using IPython with Plone 5

How did you solve this?

Sorry, late to this thread. You might have resolved/found out about this, but the scripts serve a different purpose

when bin/ipzope is generated with the zc.recipe.egg buildout recipe, it installs one or more eggs in the buildout environment and as an extra it can generate command line scripts for eggs that have a special section in their setup.py that registers the script. This is for example useful for Python modules that contain command line tools written in Python.

So what you get in this case is a python interpreter with all Python modules available on the PYTHON_PATH (i.e. loadable with from bla import x) and a generated bin/ipython script that starts the REPL.

The bin/client bin/instance bin/runwsgi scripts are generated by plone.recipe.zope2instance and those register all eggs, then start up the actual Zope application server with 'fg or console' subcommands or with debug they start up the Zope server in single thread mode and drop you in a debug prompt. Only then is the App() object available and can you do modifictions to the ZODB, etc. etc.

If you look inside the scripts you can sort of see this happening. Set/update the environment en call a start function/method in a package.

Hi @mekell

I do not know your needs exactly but on a running instance, you could try "ipdb" (ipdb · PyPI), it may be invoked by adding a @@ipdb to the url on any element when using it with iw.debug.

Gauthier

I wrote a recipe for using IPython via zconsole to debug Plone (5.2.8)

It assumes that you have a zeo Plone installation with 2 clients and client2 will be used for IPython

Create a buildout configuration file ipython-zconsole2.cfg

cd /home/Plone-5.2.8/zeocluster/
cat <<'EOF' | sudo tee ipython-zconsole2.cfg
[buildout]
extends =
    develop.cfg
eggs +=
    ipython
parts +=
    ipython-zconsole2

[ipython-zconsole2]
recipe = zc.recipe.egg
eggs =
    ipython
    ${client2:eggs}
initialization =
    from Zope2.utilities.zconsole import debug
    print('Binding app via "Zope2.utilities.zconsole.debug()" ...')
    app = debug('parts/client2/etc/zope.conf')
    print('Starting "IPython.embed()" ...')
scripts = ipython-zconsole2
entry-points = ipython-zconsole2=IPython:embed

[versions]
ipython = 8.4.0
prompt-toolkit = 3.0.30
EOF

run buildout

sudo -u buildout_user bin/buildout -c ipython-zconsole2.cfg

start your zeoserver and bin/ipython-zconsole2

sudo bin/plonectl start zeoserver
sudo -u buildout_user bin/ipython-zconsole2

in IPython you can try something like:

In [1]: print(app.title)
Zope
In [2]: plone = app.get('Plone') # <- make sure a Plone instance exists
   ...: print(plone.title)
Plone
In [3]: from zope.component.hooks import setSite
   ...: setSite(plone)
   ...: from plone import api
   ...: portal = api.portal.get()
   ...: print(portal.title)
Plone

In my example above I used the debug function of Zope2.utilities.zconsole which simply wraps make_wsgi_app from Zope2.Startup.run. Here is the updated example using make_wsgi_app directly and allowing to configure debug_mode and debug_exceptions. And showing the configuration at start if needed.

I've renamed it to ipython-with-wsgi-app.

[buildout]
extends =
    develop.cfg
eggs +=
    ipython
parts +=
    ipython-with-wsgi-app

[ipython-with-wsgi-app]
recipe = zc.recipe.egg
eggs =
    ipython
    ${client2:eggs}
initialization =
    from Zope2.Startup.run import make_wsgi_app
    # global_config = {} # or set 'debug_mode' and 'debug_exceptions' if needed
    global_config = { 'debug_mode': 'true', 'debug_exceptions': 'true' }
    zope_conf = 'parts/client2/etc/zope.conf'
    _ = make_wsgi_app(global_config, zope_conf)
    import Zope2
    app = Zope2.app()
    # uncomment the following if you want to see the configuration on start
    # from App.config import getConfiguration
    # print(getConfiguration())
scripts = ipython-with-wsgi-app
entry-points = ipython-with-wsgi-app=IPython:embed

[versions]
ipython = 8.4.0
prompt-toolkit = 3.0.30
1 Like

Late contribution on how I use iPython for debugging and maintenance.

cd Plone/zinstance
./bin/instance -OPlone debug

from IPython import start_ipython; start_ipython()

import transaction
from plone import api

portal = api.portal.get()

delete = api.content.delete
move = api.content.move
create = api.content.create

catalog = api.portal.getToolByName(portal, "portal_catalog")

While in the iPython shell, I also use the "run" command to execute scripts.
Etc...

Edit: I don't install ipython using buildout, but with pip, and only if I need it:

cd Plone/zinstance
./bin/pip install ipython

It can also be used with the debug client of a running zeo instance.

2 Likes