Jupyter is a web app which takes Python and other code types as input and executes them server-side (yes, there's JupyterLite which uses WebAssembly and Cython to execute it on the front end but it's irrelevant to this question), showing the results in the web app.
Let's say I had a good reason to want to change input values in one Python code cell based on something which happens in another code cell. Not change the value of a variable, but rather actually change a hardcoded value.
IPython (used in the Jupyter toolset) allows us to execute some JavaScript in our page via Python. So let's say the code setup look like this:
Code Cell 1:
def func(test=True, test2='hi', mitre=['T1059.001', 'T1027'], test3=['T1059.001', 'T1027']):
pass
Code Cell 2:
# Now let's say some condition has happened, maybe the user has interacted with a
# GUI IPython widget to change the application state. But we want this state to be
# saved if the user simply saves the Jupyter Notebook, which means we need to
# reflectively change the original values defined in in Code Cell 1, so the user
# doesn't need to remember to do so.
# In this case let's say we want to do something really simple, like replace 'T1027'
# with 'T1028' in the Code Cell 1 `mitre` argument.
from IPython.display import Javascript
Javascript('''
function replaceCode(value, replacement){
const codeCells = document.body.getElementsByClassName('jp-CodeCell')
for (const cell in codeCells) {
if (Object.prototype.hasOwnProperty.call(codeCells, cell)) {
const inputElem = codeCells[cell].getElementsByClassName('jp-Cell-inputWrapper')[0]
const codeLines = inputElem.querySelector('[role="presentation"]').getElementsByClassName('CodeMirror-line')
for (const line in codeLines) {
if (Object.prototype.hasOwnProperty.call(codeLines, line)) {
const codeLineSegments = codeLines[line].querySelector('[role="presentation"]');
Array.from(codeLineSegments.children).forEach(segment => {
if (segment.innerHTML == value) segment.innerHTML = replacement
})
}
}
}
}
}
replaceCode("'T1027'", "'T1028'")
''')
This code actually runs successfully and works. The values are changed. The issue is that when I click the code-cell again, it reverts to the old state. Clearly, I need to make the elements update as if they had been focused and experienced keypresses, but the normal .click()
methods and the solution I found here did not work: Is it possible to simulate key press events programmatically?
Maybe there's an easier way I'm missing, or some good solution here?