Commit 11074ebf authored by Boxiang Sun's avatar Boxiang Sun

erp5_notebook_tutorial: Add documentation about erp5 notebook

parent 6cb6bb59
<p>This is a tutorial to introduce how to create an ERP5 notebook.</p>
<h2>Introduction</h2>
<p>ERP5 notebook is unlike the tranditional notebook, such as Jupyter or Pyodidie. It is more like a static "report generate" tool rather than dynamically, interactively notebook tool. This article going to describe what should we do to use ERP5 notebook properly.</p>
<h2>Create a notebook</h2>
<p>Same as other ERP5 module, we can create a new ERP5 notebook under the Notebook Module.</p>
<p>ERP5 notebook is different from Pyodide notebook. Currently, Pyodide notebook is more interactively than ERP5 notebook, it executes cells successively and redirect the output to a widget which named "console". This "console" is not the browser's console, it created by Pyodide notebook to display all text output. In Pyodide notebook, the execution can be stopped in any cell. In ERP5 notebook, we are aim to provide a report generate tool. So ERP5 notebook will process the notebook as a whole. It not stoppable between any cells. And if we want to display something in the final report, we need to add the content explicity except the Python matplotlib figure. It means in a JS cell, we should create a HTML node, add content to it, then add this node to the DOM.</p>
<p>Despite this difference, we still using the <a href="https://github.com/iodide-project/iodide/blob/master/docs/iomd.md">iomd format</a>(the former name is jsmd). This means the erp5 notebook contains different cells, like <code># js</code>, <code># py</code>, <code># md</code> etc. Which represent JavaScript, Python, Markdown block, respectively. The text/code insides these cells will executed by corresponding parser. The Markdown contents will convert to HTML and get rendered in the final report.</p>
<p>If we only using the JS cell, the notebook could process it directly. If we need to process any Python cell, the notebook will loads and initializes the Pyodide core webassembly module. This step was automatically processed when the notebook met the first <code>%% py</code> cell. If we load Python extension explicity in a JS cell(see blow), the notebook will loads Pyodide core webassembly module if it haven't been done yet, and then loads the Python extension webassembly module.</p>
<p>It will take sometime to load the webassembly modules. The exact time is depends on your network. And it will take longer time if loads other Python extension.</p>
<h2>JS cell</h2>
<p>The notebook can launch the JS code which inside <code># js</code> normally. We can put JS code in the JS cell, calculate something or modify the document DOM. But it doesn't display anything in the report page by default. If you want show anything, you have to create an element and add it to <code>document.body</code>. Like below: </p>
<code>
# js
var div = document.createElement('div'),
pre = document.createElement('pre'),
result_element = document.createElement('code'),
result;
result = 2 + 299492456;
result_element.innerHTML = result;
pre.appendChild(result_element);
div.appendChild(pre);
document.body.appendChild(div);
</code>
<h2>Python cell</h2>
<p>Python cell is similar to JS cell. But all Python text output, aka the value printed by <code>print</code> function, will redirect to the browser's console. E.g:</p>
<code>
print(4 + 38)
</code>
<p>This line of code will print value <code>42</code> in the browser's console.</p>
<p>But for the figure generated by <code>Matplotlib</code>. The notebook will render the content to the report directly.</p>
<h3>Import Python extension</h3>
<p>For the Python standard library, we can call <code>import</code> statement directly. But for the 3rd party extension, like <code>matplotlib</code>, <code>numpy</code>. We need to create a JS cell to import the extension explicity first. For example:</p>
<code>
%% js
pyodide.loadPackage("matplotlib")
</code>
<p>The notebook will handle the dependency automatically. No need to import <code>numpy</code> manually first. Then we can call <code>import matplotlib</code> in the following Python cell. This <code>pyodide.loadPackage</code> is used for import the matplotlib webassembly module.</p>
<p>Currently, ERP5 notebook supports these 3rd party extension: cycler, kiwisolver, matplotlib, numpy, pyparsing, python-dateutil, pytz, scikit-learn, scipy.</p>
<p>Then let's see a simple Python example which use Matplotlib to draw a figure in the report:</p>
<code>
import matplotlib.pyplot as plt
plt.plot([1,23,2,4])
plt.ylabel('some numbers')
plt.show()
</code>
<p>This will display a simple figure in the final report.</p>
<h2>Summary</h2>
<p>This article introduced how to create a simple ERP5 notebook and launch JS, Python code. And the notebook are under development. Some features maybe changed. So this article will be update from time to time. Like we may redirect the output of a <code>print</code> function to the final report. And also add a parser in the notebook. If encountered a import statement which trying to import a 3rd party Python extension, let the notebook load it automatically.</p>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Page" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>erp5-Notebook.Tutorial.1.Hello.World</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5-Notebook.Tutorial.1.Hello.World.001.en</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value> <string>en</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Page</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value> <string>Hello World</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>ERP5 Notebook Tutorial 1 - Hello World</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>document_publication_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>processing_status_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_alive</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1566921301.97</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published_alive</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>edit</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>978.2590.64831.3993</string> </value>
</item>
<item>
<key> <string>state</string> </key>
<value> <string>current</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1566980773.87</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_processing_state</string> </key>
<value> <string>empty</string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1566813446.81</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
Copyright 2019, Nexedi SA
\ No newline at end of file
This bt5 contains ERP5 Notebook user documentation
\ No newline at end of file
Creative Common Attribution NonCommercial ShareAlike
\ No newline at end of file
web_page_module/erp5-Notebook.Tutorial.1.Hello.World.001.en
\ No newline at end of file
web_page_module/erp5-Notebook.Tutorial.1.Hello.World.001.en
\ No newline at end of file
erp5_notebook_tutorial
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment