Notebook objects

Notebook cells and outputs and helpers.
bridge_cfg.auto_show = True

Notebook data

Example nbformat state:

{
    "type": "state",  // "state" | ...
    "cells": [
        // Markdown cell
        {
            "cell_type": 1,  // 1: markdown, 2: code
            "source": "string",  // Cell content
            "metadata"?: {  // Optional
                "tags": ["string"],
                "jupyter": { /* jupyter specific */ },
                "brd": {
                    "id": "string", 
                    "renderer": bool  // optional
                }
            },
            "id": "string"
        },
        // Code cell with outputs
        {
            "cell_type": 2,
            "source": "string",
            "outputs"?: [  // Optional, only for code cells
                {
                    "output_type": 1 | 2 | 3 | 4 // "stream" | "display_data" | "execute_result" | "error",
                    "metadata"?: {...},  // Optional
                    // Type-specific fields
                    "name"?: "stdout" | "stderr",  // For stream
                    "text"?: "string",             // For stream
                    "data"?: {  // Optional
                        "mime/type": "string"  // e.g., "text/plain": "content"
                    },
                    "ename"?: "string",            // For error
                    "evalue"?: "string",           // For error
                    "traceback"?: ["string"],      // For error
                    "execution_count"?: number     // For execute_result
                }
            ]
        }
    ]
}
test_fn = ( '../packages/nbinspect-vscode/test/outputs.json'
            if in_vscode else 
            '../packages/nbinspect-lab/nbs/outputs.json')
test_json = Path(test_fn).read_text('utf-8')
state = json.loads(test_json)

# cprint(state, width=120, overflow='ellipsis')
RenderJSON(state, init_level=2, max_height=400).display()
def f(c):
    cc = deepcopy(c)
    if in_vscode:
        brd = cc['metadata']['brd']
        # vscode cell_id is not well formed nbformat's cell id
        brd['cell_id'], cc['id'] = cc['id'], brd['id']
        del brd['id']
    del cc['idx']
    return cc

cells = map(f, state['cells'])
md = state['nbData']['metadata']
nb_md = {
    'kernel_info': md['metadata']['kernelspec'],
}
if 'language_info' in md['metadata']: nb_md['language_info'] = md['metadata']['language_info']
nb = {
    'cells': list(cells)[:],
    'metadata': nb_md,
    'nbformat': md['nbformat'],
    'nbformat_minor': 5 # md['nbformat_minor']
}
RenderJSON(nb, init_level=2, max_height=400).display()
nb = nbformat.reads(json.dumps(nb), as_version=nbformat.NO_CONVERT, capture_validation_error=(derr := {}))
test_eq(derr, {})

NBCell

Note: though using AD for convenience, NBCell should be considered immutable.


source

has_directive

 has_directive (c:__main__.NBCell, directive:str, *args)

source

NBOutputError

 NBOutputError (out:Mapping)

dict subclass that also provides access to keys as attrs


source

NBOutputExecuteResult

 NBOutputExecuteResult (out:Mapping)

dict subclass that also provides access to keys as attrs


source

NBOutputDisplayData

 NBOutputDisplayData (out:Mapping)

dict subclass that also provides access to keys as attrs


source

NBOutputStream

 NBOutputStream (out:Mapping)

dict subclass that also provides access to keys as attrs


source

NBOutput

 NBOutput (out:Mapping)

dict subclass that also provides access to keys as attrs


source

NBCellCode

 NBCellCode (cell:Mapping)

dict subclass that also provides access to keys as attrs


source

NBCellMarkdown

 NBCellMarkdown (cell:Mapping)

dict subclass that also provides access to keys as attrs


source

NBCellRaw

 NBCellRaw (cell:Mapping)

dict subclass that also provides access to keys as attrs


source

NBCell

 NBCell (cell:Mapping)

dict subclass that also provides access to keys as attrs

test_eq(NBCell({}), NBCellRaw({}))
test_eq(NBCell(AD(cell_type='markdown')), {'cell_type': 'markdown', 'source': ''})
test_eq(
    NBCell(AD(cell_type='code', source='print("hello")')), 
    {'cell_type': 'code', 'source': 'print("hello")', 'outputs': []})
test_eq(
    NBCell(
        AD(cell_type='code', source='display("hello")', 
            outputs=[AD(output_type='display_data', data={'text/plain': 'hello'})])),
    {'cell_type': 'code', 'source': 'display("hello")', 'outputs': [AD(output_type='display_data', data={'text/plain': 'hello'})]})
test_eq(
    NBCell({
        'cell_type': 'code',
        'source': "display(HTML('cell 4'))\n",
        'outputs': ({
            'output_type': 'display_data',
            'data': {'text/html': 'cell 4', 'text/plain': '<IPython.core.display.HTML object>'},
            },)}),
    {'cell_type': 'code', 'source': "display(HTML('cell 4'))\n", 'outputs': [AD(output_type='display_data', data={'text/html': 'cell 4', 'text/plain': '<IPython.core.display.HTML object>'})]})
c1 = NBCell(dict(cell_type='code', source='display("hello")'))
c2 = NBCell(c1)
test_is(c1, c2)

c3 = c2.copy()
test_is(c1 is c3, False)
test_eq(c1.source, c3.source)
test_eq(c1.outputs, c3.outputs)
state['cells'][1]
{'idx': 1,
 'cell_type': 'code',
 'source': '# cell 1\nimport time\nfrom itertools import count\n\nimport ipywidgets as W\nimport matplotlib.pyplot as plt\nfrom bridget.helpers import displaydh\nfrom IPython.display import HTML, Image, Javascript, JSON, DisplayHandle, clear_output\ncounter = count()',
 'id': 'W1sZmlsZQ==',
 'metadata': {'brd': {'id': '717322f8-95fa-425c-839d-8b9e7d4ef921'}},
 'outputs': [],
 'execution_count': 1}
NBCell(state['cells'][1])
NBCell@1
  • idx: 1
  • cell_type: code
  • source: # cell 1 import time from itertools import count import ipywidgets as W import matplotlib.pyplot as plt from bridget.helpers import display…
  • id: W1sZmlsZQ==
  • metadata: {'brd': {'id': '717322f8-95fa-425c-839d-8b9e7d4ef921'}}
  • outputs
    • execution_count: 1
    cell = NBCell(state['cells'][2])
    test_is(type(cell), NBCellCode)
    test_eq_type(cell.outputs[0], NBOutput(AD(output_type='stream', name='stdout', text='1\n')))
    cell
    NBCell@2
    • idx: 2
    • cell_type: code
    • source: # cell 2 print(1)
    • id: W2sZmlsZQ==
    • metadata: {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}}
    • outputs
        0
        • output_type: stream
        • name: stdout
        • text: 1
    • execution_count: 2
    cell = NBCell(state['cells'][4])
    test_is(type(cell), NBCellCode)
    cell
    NBCell@4
    • idx: 4
    • cell_type: code
    • source: # cell 4 import time time.sleep(2) displaydh(HTML('cell 4'), metadata={'bridge': {'cell': 4}});
    • id: W4sZmlsZQ==
    • metadata: {'brd': {'id': '798f7f83-9b31-4e21-a36b-5520c6f72a2d'}}
    • outputs
        0
        • output_type: display_data
        • data
          • text/html: cell 4
          • text/plain: <IPython.core.display.HTML object>
        • metadata: {'transient': {'display_id': '2ffe60c5c571592fc61fe81faab39e34'}, 'bridge': {'cell': 4}}
    • execution_count: 4

    did

    nested_idx(cell, 'outputs', 0, 'metadata', 'transient', 'display_id')
    '2ffe60c5c571592fc61fe81faab39e34'
    test_eq(nested_idx(NBCell(state['cells'][0]), 'outputs', 0, 'metadata', 'transient', 'display_id'), None)
    nested_idx(getattr(NBCell(state['cells'][3]), 'outputs'), 0, 'metadata', 'transient', 'display_id')
    '9d0548d3b88c66b7def8b47bbe5a12dd'
    cell = NBCell(state['cells'][8])
    display(cell.outputs[0])
    nested_idx(cell, 'outputs', 0, 'metadata', 'transient', 'display_id'), val_atpath(cell, 'outputs', 0, 'metadata', 'transient', 'display_id', default=None)
    { 'data': { 'text/html': '<h3>cell 8</h3>\n',
                'text/plain': '<IPython.core.display.HTML object>'},
      'metadata': {'transient': {}},
      'output_type': 'display_data'}
    ({}, None)

    can’t use nexsted_idx.


    source

    did

     did (o:__main__.NBOutput)
    # type: ignore
    
    cell = NBCell(state['cells'][4])
    display(cell.outputs[0])
    
    test_eq(did(cell.outputs[0]), cell.outputs[0]['metadata']['transient']['display_id'])
    test_eq(cell.outputs[0].did, cell.outputs[0]['metadata']['transient']['display_id'])
    { 'data': { 'text/html': 'cell 4',
                'text/plain': '<IPython.core.display.HTML object>'},
      'metadata': { 'bridge': {'cell': 4},
                    'transient': { 'display_id': '2ffe60c5c571592fc61fe81faab39e34'}},
      'output_type': 'display_data'}
    cell = NBCell(state['cells'][2])
    display(cell.outputs[0])
    test_eq(did(cell.outputs[0]), None)
    {'name': 'stdout', 'output_type': 'stream', 'text': '1\n'}
    cell = NBCell(state['cells'][8])
    display(cell.outputs[0])
    { 'data': { 'text/html': '<h3>cell 8</h3>\n',
                'text/plain': '<IPython.core.display.HTML object>'},
      'metadata': {'transient': {}},
      'output_type': 'display_data'}
    cell = NBCell(state['cells'][8])
    display(cell.outputs[0])
    test_eq(did(cell.outputs[0]), None)
    { 'data': { 'text/html': '<h3>cell 8</h3>\n',
                'text/plain': '<IPython.core.display.HTML object>'},
      'metadata': {'transient': {}},
      'output_type': 'display_data'}

    dids


    source

    dids

    cell = NBCell(state['cells'][5])
    display(cell.outputs)
    test_eq(cell.dids, [cell.outputs[0].did])
    [{'output_type': 'display_data',
      'data': {'application/javascript': 'console.log("cell 5")',
       'text/plain': '<IPython.core.display.Javascript object>'},
      'metadata': {'transient': {'display_id': 'b970be042e0ebd1e5af19aadcfbf213e'},
       'bridge': {'cell': 5}}}]
    test_eq(NBCell(state['cells'][1]).dids, [])
    display(state['cells'][2])
    test_eq(NBCell(state['cells'][1]).dids, [])
    {'idx': 2,
     'cell_type': 'code',
     'source': '# cell 2\nprint(1)',
     'id': 'W2sZmlsZQ==',
     'metadata': {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}},
     'outputs': [{'output_type': 'stream', 'name': 'stdout', 'text': '1\n'}],
     'execution_count': 2}
    display(cell := NBCell(state['cells'][7]))
    cell.dids
    NBCell@7
    • idx: 7
    • cell_type: code
    • source: # cell 7 displaydh(HTML('cell 7.1'), metadata={'bridge': {'cell': 7.1}}) displaydh(HTML('cell 7.2'), metadata={'bridge': {'cell': 7.2}});
    • id: X10sZmlsZQ==
    • metadata: {'brd': {'id': '7512abfe-f7d2-4047-a6b1-56aefbf9457e'}}
    • outputs
        0
        • output_type: display_data
        • data
          • text/html: cell 7.1
          • text/plain: <IPython.core.display.HTML object>
        • metadata: {'transient': {'display_id': '331d2582eb05fdc75afaa4c616fc8b6c'}, 'bridge': {'cell': 7.1}}
        1
        • output_type: display_data
        • data
          • text/html: cell 7.2
          • text/plain: <IPython.core.display.HTML object>
        • metadata: {'transient': {'display_id': 'bbb4397c26ce0c3fb2f1acddc6ce91b1'}, 'bridge': {'cell': 7.2}}
    • execution_count: 7
    (#2) ['331d2582eb05fdc75afaa4c616fc8b6c','bbb4397c26ce0c3fb2f1acddc6ce91b1']
    cells = L(state['cells']).map(NBCell)
    cells.map(lambda c: NBCell(c).dids)
    (#42) [[],[],[],['9d0548d3b88c66b7def8b47bbe5a12dd'],['2ffe60c5c571592fc61fe81faab39e34'],['b970be042e0ebd1e5af19aadcfbf213e'],[],['331d2582eb05fdc75afaa4c616fc8b6c', 'bbb4397c26ce0c3fb2f1acddc6ce91b1'],[],[],[],[],[],[],[],[],['a6b5cc5f13bf64ce8dd73d0b79b0bef2'],['b0c4b491988399c7d88a82779528132d'],[],['e81dd25b299e4881aff6aec417c5bed9']...]
    test_eq(cells[2]['outputs'][0]['name'], 'stdout')  # type: ignore
    test_eq(len(codes := cells.argwhere(lambda c: c['cell_type'] == 'code')), 40)
    display(codes)
    cells[codes[2]]
    (#40) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...]
    NBCell@3
    • idx: 3
    • cell_type: code
    • source: # cell 3 displaydh('cell 3', metadata={'bridge': {'cell': 3}});
    • id: W3sZmlsZQ==
    • metadata: {'brd': {'id': 'f2c19c18-a3f7-4acb-88e4-c7239178c401'}}
    • outputs
        0
        • output_type: display_data
        • data
          • text/plain: 'cell 3'
        • metadata: {'transient': {'display_id': '9d0548d3b88c66b7def8b47bbe5a12dd'}, 'bridge': {'cell': 3}}
    • execution_count: 3

    by_type


    source

    by_type

     by_type (cells:Union[Sequence[__main__.NBCell],fastcore.foundation.L],
              cell_type:Literal['code','markdown'])

    Return ‘L’ of indices of cells of type cell_type

    by_type(cells, 'code')
    (#40) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...]
    by_type(cells, 'code')
    (#40) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...]

    idx2cell

    idxs = by_type(cells, 'code')
    idxs
    (#40) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...]
    cells[idxs][:5]

    source

    idx2cell

     idx2cell (cells:Union[Sequence[__main__.NBCell],fastcore.foundation.L],
               cell_type:Optional[Literal['code','markdown']]=None)

    Return mapping of indices to cells of type cell_type

    test_eq(all(isinstance(c, NBCellCode) for c in idx2cell(cells, 'code').values()), True)
    idx2cell(cells, 'code').keys()
    dict_keys([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41])
    idx2cell(cells, 'code')[1]
    NBCell@1
    • idx: 1
    • cell_type: code
    • source: # cell 1 import time from itertools import count import ipywidgets as W import matplotlib.pyplot as plt from bridget.helpers import display…
    • id: W1sZmlsZQ==
    • metadata: {'brd': {'id': '717322f8-95fa-425c-839d-8b9e7d4ef921'}}
    • outputs
      • execution_count: 1

      withOutputs

      outputs_idx = cells.argwhere(lambda c: 'outputs' in c)
      display(outputs_idx)
      
      print(outputs_idx.zipwith(cells[outputs_idx])[0])
      
      dict(outputs_idx.zipwith(cells[outputs_idx]))[3]
      (#40) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...]
      (1, {'idx': 1, 'cell_type': 'code', 'source': '# cell 1\nimport time\nfrom itertools import count\n\nimport ipywidgets as W\nimport matplotlib.pyplot as plt\nfrom bridget.helpers import displaydh\nfrom IPython.display import HTML, Image, Javascript, JSON, DisplayHandle, clear_output\ncounter = count()', 'id': 'W1sZmlsZQ==', 'metadata': {'brd': {'id': '717322f8-95fa-425c-839d-8b9e7d4ef921'}}, 'outputs': [], 'execution_count': 1})
      NBCell@3
      • idx: 3
      • cell_type: code
      • source: # cell 3 displaydh('cell 3', metadata={'bridge': {'cell': 3}});
      • id: W3sZmlsZQ==
      • metadata: {'brd': {'id': 'f2c19c18-a3f7-4acb-88e4-c7239178c401'}}
      • outputs
          0
          • output_type: display_data
          • data
            • text/plain: 'cell 3'
          • metadata: {'transient': {'display_id': '9d0548d3b88c66b7def8b47bbe5a12dd'}, 'bridge': {'cell': 3}}
      • execution_count: 3

      source

      withOutputs

       withOutputs
                    (cells:Union[Sequence[__main__.NBCell],fastcore.foundation.L
                    ])

      Return indices of cells with outputs

      withOutputs(cells[:5])
      (#4) [1,2,3,4]

      idx2outputs


      source

      idx2outputs

       idx2outputs
                    (cells:Union[Sequence[__main__.NBCell],fastcore.foundation.L
                    ])

      Return dict of indices to cells with outputs

      idx2outputs(cells)[2]
      NBCell@2
      • idx: 2
      • cell_type: code
      • source: # cell 2 print(1)
      • id: W2sZmlsZQ==
      • metadata: {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}}
      • outputs
          0
          • output_type: stream
          • name: stdout
          • text: 1
      • execution_count: 2
      idx2outputs(cells)[7]
      NBCell@7
      • idx: 7
      • cell_type: code
      • source: # cell 7 displaydh(HTML('cell 7.1'), metadata={'bridge': {'cell': 7.1}}) displaydh(HTML('cell 7.2'), metadata={'bridge': {'cell': 7.2}});
      • id: X10sZmlsZQ==
      • metadata: {'brd': {'id': '7512abfe-f7d2-4047-a6b1-56aefbf9457e'}}
      • outputs
          0
          • output_type: display_data
          • data
            • text/html: cell 7.1
            • text/plain: <IPython.core.display.HTML object>
          • metadata: {'transient': {'display_id': '331d2582eb05fdc75afaa4c616fc8b6c'}, 'bridge': {'cell': 7.1}}
          1
          • output_type: display_data
          • data
            • text/html: cell 7.2
            • text/plain: <IPython.core.display.HTML object>
          • metadata: {'transient': {'display_id': 'bbb4397c26ce0c3fb2f1acddc6ce91b1'}, 'bridge': {'cell': 7.2}}
      • execution_count: 7
      idx2outputs(cells)[12]
      NBCell@12
      • idx: 12
      • cell_type: code
      • source: # cell 12 W.IntSlider(12, description='cell')
      • id: X15sZmlsZQ==
      • metadata: {'brd': {'id': 'e7e6d557-3aa7-41a7-9e77-805295112aec'}}
      • outputs
          0
          • output_type: execute_result
          • data
              application/vnd.jupyter.widget-view+json
              • version_major: 2
              • version_minor: 0
              • model_id: 6191b18d61a44fbd89eb132d22a28eab
            • text/plain: IntSlider(value=12, description='cell')
          • execution_count: 12
          • metadata: {}
      • execution_count: 12

      idx2dids

      outputs_idx = withOutputs(cells := L(cells))
      outputs_idx
      (#40) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...]
      outputs_idx.zipwith(cells[outputs_idx]).filter(lambda c: c[1].dids)[:2]
      (#2) [(3, {'idx': 3, 'cell_type': 'code', 'source': "# cell 3\ndisplaydh('cell 3', metadata={'bridge': {'cell': 3}});", 'id': 'W3sZmlsZQ==', 'metadata': {'brd': {'id': 'f2c19c18-a3f7-4acb-88e4-c7239178c401'}}, 'outputs': [{'output_type': 'display_data', 'data': {'text/plain': "'cell 3'"}, 'metadata': {'transient': {'display_id': '9d0548d3b88c66b7def8b47bbe5a12dd'}, 'bridge': {'cell': 3}}}], 'execution_count': 3}),(4, {'idx': 4, 'cell_type': 'code', 'source': "# cell 4\nimport time\ntime.sleep(2)\ndisplaydh(HTML('cell 4'), metadata={'bridge': {'cell': 4}});", 'id': 'W4sZmlsZQ==', 'metadata': {'brd': {'id': '798f7f83-9b31-4e21-a36b-5520c6f72a2d'}}, 'outputs': [{'output_type': 'display_data', 'data': {'text/html': 'cell 4', 'text/plain': '<IPython.core.display.HTML object>'}, 'metadata': {'transient': {'display_id': '2ffe60c5c571592fc61fe81faab39e34'}, 'bridge': {'cell': 4}}}], 'execution_count': 4})]

      source

      idx2dids

       idx2dids (cells:Union[Sequence[__main__.NBCell],fastcore.foundation.L])

      Return dict of indices to cells with transient outputs

      idx2dids(cells).keys(), idx2dids(cells)[7]
      (dict_keys([3, 4, 5, 7, 16, 17, 19, 24, 26, 35]),
       (#2) ['331d2582eb05fdc75afaa4c616fc8b6c','bbb4397c26ce0c3fb2f1acddc6ce91b1'])

      directives

      NBCells register nbdev directives/quarto Cell options/python cell magics in directives_.

      s = '''
      
      #| hide
      
      print(1)
      '''
      cell1 = NBCell(AD(cell_type='code', source=s))
      test_is(cell1.has_directive('hide'), True)
      cell1.directives_
      {'python': [], 'hide': []}
      s = '''
      #| label: fig-polar
      #| echo: false
      
      # comment
      print(1)
      '''
      cell2 = NBCell(dict(cell_type='code', source=s))
      cell2.directives_
      {'label:': ['fig-polar'], 'echo:': ['false']}
      s = '''
      
          #| code-fold
      
      print(1)
      '''
      cell3 = NBCell({'cell_type':'code', 'source':s})
      cell3.directives_
      {'code-fold': []}

      source

      by_directive

       by_directive
                     (cells:Union[Sequence[__main__.NBCell],fastcore.foundation.
                     L], directive:str, *args)
      test_eq(by_directive([cell1, cell2, cell3], 'hide'), [0])

      NB

      {'a', 'b'} & {'a', 'c'}
      {'a'}

      source

      NB

       NB (cells:Union[Sequence[__main__.NBCell],fastcore.foundation.L]=(),
           **kwargs)

      Bridget representation of notebook state


      source

      NBProcessor

       NBProcessor (*args, **kwargs)

      Callable that transforms a notebook and returns the result


      source

      NBProvider

       NBProvider (*args, **kwargs)

      Objects that provide access to a notebook (NB) instance

      test_eq(NB().as_dict(), {'cells': [], 'nbData': {}, 'type': 'state', 'timestamp': '', 'origin': ''})
      test_eq(NB(nbData={'a':1}).as_dict(), {'cells': [], 'nbData':{'a':1}, 'type': 'state', 'timestamp': '', 'origin': ''})
      nb = NB.fromStateMessage(state)
      cells = nb.cells
      
      test_eq(len(nb.cells), nb.nbData['cellCount'])
      test_eq(nb.nbData['metadata']['nbformat'], 4)
      (c := nb.cells[2])
      NBCell@2
      • idx: 2
      • cell_type: code
      • source: # cell 2 print(1)
      • id: W2sZmlsZQ==
      • metadata: {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}}
      • outputs
          0
          • output_type: stream
          • name: stdout
          • text: 1
      • execution_count: 2
      test_eq(c, nb[2])
      test_eq(nb[c.id], nb[2])  # type: ignore
      nb[12]
      NBCell@12
      • idx: 12
      • cell_type: code
      • source: # cell 12 W.IntSlider(12, description='cell')
      • id: X15sZmlsZQ==
      • metadata: {'brd': {'id': 'e7e6d557-3aa7-41a7-9e77-805295112aec'}}
      • outputs
          0
          • output_type: execute_result
          • data
              application/vnd.jupyter.widget-view+json
              • version_major: 2
              • version_minor: 0
              • model_id: 6191b18d61a44fbd89eb132d22a28eab
            • text/plain: IntSlider(value=12, description='cell')
          • execution_count: 12
          • metadata: {}
      • execution_count: 12

      source

      NB.by_type

       NB.by_type (cell_type:Literal['code','markdown'])

      Return indices of cells of type cell_type

      display(nb[2])
      test_eq(cells[2].outputs[0].name, 'stdout')  # type: ignore
      NBCell@2
      • idx: 2
      • cell_type: code
      • source: # cell 2 print(1)
      • id: W2sZmlsZQ==
      • metadata: {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}}
      • outputs
          0
          • output_type: stream
          • name: stdout
          • text: 1
      • execution_count: 2
      nb.by_type('code')
      (#40) [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...]

      source

      NB.codes

      Cell indices of type code


      source

      NB.mds

      Cell indices of type markdown

      nb.mds
      (#2) [0,23]

      source

      NB.idx2cell

       NB.idx2cell (cell_type:Optional[Literal['code','markdown']]=None)

      Return dict of indices to cells of type cell_type

      nb.idx2cell('code')[2]
      NBCell@2
      • idx: 2
      • cell_type: code
      • source: # cell 2 print(1)
      • id: W2sZmlsZQ==
      • metadata: {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}}
      • outputs
          0
          • output_type: stream
          • name: stdout
          • text: 1
      • execution_count: 2

      source

      NB.idx2code

      Return dict of indices to cells of type code


      source

      NB.idx2md

      Return dict of indices to cells of type markdown

      nb.idx2md[0]
      NBCell@0
      • idx: 0
      • cell_type: markdown
      • source: # cell 0
      • id: W0sZmlsZQ==
      • metadata: {'brd': {'id': '81c3e877-b59a-48f5-a1da-21894d928d4b'}}

      source

      NB.withOutputs

      Return indices of cells with outputs


      source

      NB.idx2outputs

      Return dict of indices to cells with outputs

      # type: ignore
      
      display(cells[codes[2]].outputs[0])
      
      test_eq(did(cells[codes[2]].outputs[0]), cells[codes[2]].outputs[0].metadata['transient']['display_id'])
      test_eq(cells[codes[2]].outputs[0].did, cells[codes[2]].outputs[0].metadata['transient']['display_id'])
      { 'data': {'text/plain': "'cell 3'"},
        'metadata': { 'bridge': {'cell': 3},
                      'transient': { 'display_id': '9d0548d3b88c66b7def8b47bbe5a12dd'}},
        'output_type': 'display_data'}
      print(nb.idx2outputs.keys())
      display(nb.idx2outputs[1])
      nb.idx2outputs[2]
      dict_keys([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41])
      NBCell@1
      • idx: 1
      • cell_type: code
      • source: # cell 1 import time from itertools import count import ipywidgets as W import matplotlib.pyplot as plt from bridget.helpers import display…
      • id: W1sZmlsZQ==
      • metadata: {'brd': {'id': '717322f8-95fa-425c-839d-8b9e7d4ef921'}}
      • outputs
        • execution_count: 1
        NBCell@2
        • idx: 2
        • cell_type: code
        • source: # cell 2 print(1)
        • id: W2sZmlsZQ==
        • metadata: {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}}
        • outputs
            0
            • output_type: stream
            • name: stdout
            • text: 1
        • execution_count: 2
        (cell := nb.idx2outputs[7])
        NBCell@7
        • idx: 7
        • cell_type: code
        • source: # cell 7 displaydh(HTML('cell 7.1'), metadata={'bridge': {'cell': 7.1}}) displaydh(HTML('cell 7.2'), metadata={'bridge': {'cell': 7.2}});
        • id: X10sZmlsZQ==
        • metadata: {'brd': {'id': '7512abfe-f7d2-4047-a6b1-56aefbf9457e'}}
        • outputs
            0
            • output_type: display_data
            • data
              • text/html: cell 7.1
              • text/plain: <IPython.core.display.HTML object>
            • metadata: {'transient': {'display_id': '331d2582eb05fdc75afaa4c616fc8b6c'}, 'bridge': {'cell': 7.1}}
            1
            • output_type: display_data
            • data
              • text/html: cell 7.2
              • text/plain: <IPython.core.display.HTML object>
            • metadata: {'transient': {'display_id': 'bbb4397c26ce0c3fb2f1acddc6ce91b1'}, 'bridge': {'cell': 7.2}}
        • execution_count: 7
        def get_data(cell: NBCell, mime:str|None=None): 
            return d.get(mime, None) if (d := nested_idx(cell, 'outputs', 0, 'data')) and mime else d
        get_html = partial(get_data, mime='text/html')
        get_plain = partial(get_data, mime='text/plain')
        
        print(f"{get_data(cell)=}\n{get_html(cell)=}\n{get_plain(cell)=}")
        get_data(cell)={'text/html': 'cell 7.1', 'text/plain': '<IPython.core.display.HTML object>'}
        get_html(cell)='cell 7.1'
        get_plain(cell)='<IPython.core.display.HTML object>'

        source

        NB.process

         NB.process
                     (cbs:Union[pote.callback.Callback,Sequence[pote.callback.Call
                     back]]=(), slc:slice|None=None,
                     pred:Optional[Callable[[__main__.NBCell],bool]]=None,
                     **kwargs)

        Process a subset slc of cells filtered by pred with cbs and FuncCB callbacks.

        Type Default Details
        cbs Union ()
        slc slice | None None
        pred Optional None
        kwargs VAR_KEYWORD
        Returns NB FuncCB kwargs
        nb.process(on_iter=lambda _,item: print(item.cell_type, end=', '));
        markdown, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, markdown, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, code, 
        ctyps = []
        cb = FuncCB(on_iter=lambda _,item: ctyps.append(item.cell_type))
        process_(nb.cells, cb)
        test_eq(ctyps, [c.cell_type for c in nb.cells])
        
        ctyps = []
        nb.process(slc=slice(0,2), on_iter=lambda _,item: ctyps.append(item.cell_type))
        test_eq(ctyps, ('markdown', 'code'))
        nb.process(on_iter=lambda _,item: print((_.n, item.cell_type), end=', '));
        (0, 'markdown'), (1, 'code'), (2, 'code'), (3, 'code'), (4, 'code'), (5, 'code'), (6, 'code'), (7, 'code'), (8, 'code'), (9, 'code'), (10, 'code'), (11, 'code'), (12, 'code'), (13, 'code'), (14, 'code'), (15, 'code'), (16, 'code'), (17, 'code'), (18, 'code'), (19, 'code'), (20, 'code'), (21, 'code'), (22, 'code'), (23, 'markdown'), (24, 'code'), (25, 'code'), (26, 'code'), (27, 'code'), (28, 'code'), (29, 'code'), (30, 'code'), (31, 'code'), (32, 'code'), (33, 'code'), (34, 'code'), (35, 'code'), (36, 'code'), (37, 'code'), (38, 'code'), (39, 'code'), (40, 'code'), (41, 'code'), 
        def _enumerate(istat, item:NBCell): 
            item.metadata['n'] = istat.n
        
        test_eq(vals_at(nb.cells, '*.metadata.n'), ())
        nb.process(on_iter=_enumerate);
        test_eq(vals_at(nb.cells, '*.metadata.n'), range(len(nb.cells)))

        source

        NB.pipe

         NB.pipe (funcs:Iterable[__main__.NBProcessor], *args, **kwargs)

        Pipe a sequence of NBProcessors

        nb.pipe((lambda nb: NB.from_NB(nb, nb.cells[nb.mds]),)).cells.attrgot('source')
        (#2) ['# cell 0','# cell 23']

        source

        NB.cell_by_did

         NB.cell_by_did (did:str)
        test_eq(nb.cell_by_did(nb[7].dids[1]), nb[7])

        Diffs

        def check(self:NB):
            test_eq(self.nbData['cellCount'], len(self.cells))
            for n, c in enumerate(self.cells):
                test_eq(c.idx, n)
        
        check(nb)
        state = json.loads(Path(test_fn).read_text('utf-8'))
        nb = NB.fromStateMessage(state)
        test_eq(len(nb.cells), nb.nbData['cellCount'])
        # update existing cell
        diffs1 = json.loads(Path('../packages/nbinspect-vscode/test/update01_chg_2.json').read_text('utf-8'))
        RenderJSON(diffs1, init_level=4, max_height=400).display()
        def apply_diff(nb:NB, diff):
            changed, added, removed, cellCount = gets(diff, 'cells', 'added', 'removed', 'cellCount')
            cells = nb.cells
            for cell in changed:  # type: ignore
                cell = NBCell(cell)
                cells[cell.idx] = cell
        
        apply_diff(nb, diffs1['changes'][0])
        check(nb)
        # remove cell
        diffs2 = json.loads(Path('../packages/nbinspect-vscode/test/update13_remove_2-3-5.json').read_text('utf-8'))
        RenderJSON(diffs2, init_level=5, max_height=400).display()
        def apply_diff(nb:NB, diff):
            changed, added, removed, cellCount = gets(diff, 'cells', 'added', 'removed', 'cellCount')
            cells = nb.cells
            if removed:
                for idx in sorted(removed, reverse=True):  # type: ignore
                    del cells[idx]
                    for cell in cells[idx:]:
                        cell.idx -= 1
            nb.nbData['cellCount'] = cellCount
            for cell in changed:  # type: ignore
                cells[cell.idx] = NBCell(cell)
        
        nb = NB.fromStateMessage(state)
        apply_diff(nb, diffs2['changes'][0])
        apply_diff(nb, diffs2['changes'][1])
        check(nb)
        # cells added
        diffs3 = json.loads(Path('../packages/nbinspect-vscode/test/update14-add_2-3-4.json').read_text('utf-8'))
        RenderJSON(diffs3, init_level=4, max_height=400).display()
        nb = NB.fromStateMessage(state)
        
        nb._apply_diff(diffs1['changes'][0])
        nb._apply_diff(diffs2['changes'][0])
        nb._apply_diff(diffs2['changes'][1])
        nb._apply_diff(diffs3['changes'][0])
        check(nb)
        # type: ignore
        nb = NB.fromStateMessage(state)
        
        nb._apply_diff({'cells': [], 'added': [], 'removed': [], 'cellCount': 42})
        check(nb)
        
        with test_raises(IndexError):
            nb._apply_diff({'cells': [], 'added': [], 'removed': [], 'cellCount': 134})
        
        nb._apply_diff({'cells': [], 'added': [], 'removed': [3, 5], 'cellCount': 40})
        check(nb)
        
        with test_raises(IndexError):
            nb._apply_diff({'cells': [], 'added': [], 'removed': [3, 5], 'cellCount': 40})
        
        with test_raises(IndexError):
            nb._apply_diff({'added': [{'idx': 50}], 'cells': [], 'removed': [], 'cellCount': 41})
        
        with test_raises(IndexError):
            nb._apply_diff({'removed': [43], 'cells': [], 'added': [], 'cellCount': 40})
        
        with test_raises(IndexError):
            nb._apply_diff({'cells': [{'idx': 41}], 'added': [], 'removed': [], 'cellCount': 40})

        source

        show_doc

         show_doc (sym, renderer=None, name:str|None=None, title_level:int=3)

        Show signature and docstring for sym

        Type Default Details
        sym Symbol to document
        renderer NoneType None Optional renderer (defaults to markdown)
        name str | None None Optionally override displayed name of sym
        title_level int 3 Heading level to use for symbol name
        nb = NB.fromStateMessage(state)
        
        ff = sorted(Path('../packages/nbinspect-vscode/test/').glob('update*.json'))
        for f in ff[:12]:
            diffs = json.loads(f.read_text('utf-8'))
            nb.apply_diffsMessage(diffs)
        check(nb)
        nb = NB.fromStateMessage(state)
        
        for f in ff[12:]:
            diffs = json.loads(f.read_text('utf-8'))
            nb.apply_diffsMessage(diffs)
        check(nb)

        IpynbConvertCB

        Notebook state to IPython notebook format (ipynb)

        NBCell and friends are mostly Notebook format types without enforcing some attributes. Going back and forth between the two formats is easy.


        source

        St2Ipynb

         St2Ipynb (in_vscode:bool=False)

        Delegates (__call__,decode,setup) to (encodes,decodes,setups) if split_idx matches


        source

        IpynbCell

        dict subclass that also provides access to keys as attrs


        source

        IpynbOutput

        dict subclass that also provides access to keys as attrs

        cell = NBCell({
            'cell_type': 'code', 'source': '', 'idx': 1, 'id': 'asdfg',
            'metadata': {'brd': {'id': '123-456'}},
            'outputs': [{
                'output_type': 'display_data',
                'data': {'text/plain': ''},
                'metadata': {'transient': {'display_id': 'abc'}}
            }]
        })
        c = St2Ipynb(in_vscode)(cell)
        test_eq(type(c), IpynbCell)
        test_eq(c.outputs[0].metadata, {})
        test_eq(c.id, '123-456' if in_vscode else 'asdfg')
        test_fail(lambda: c.idx)
        nb = NB.fromStateMessage(state)
        
        icells = nb.cells.map(St2Ipynb(in_vscode))
        RenderJSON(icells, init_level=1, max_height=400).display()

        source

        IpynbConvertCB

         IpynbConvertCB (in_vscode:bool=False)

        Base class of callbacks.

        # processor = BridgetNBProcessor(state)
        nb.process(cb := IpynbConvertCB(in_vscode))
        ipynb_json = cb.notebook
        
        nb = nbformat.reads(json.dumps(ipynb_json), as_version=nbformat.NO_CONVERT, capture_validation_error=(derr := {}))
        test_eq(derr, {})
        
        RenderJSON(ipynb_json, init_level=1, max_height=400).display()

        MDConvertCB

        StateConversionCB

        Find

        class FindCB(Callback):
            def __init__(self, what:str|Callable[[NBCell], bool], where:str='source'): 
                self.what = (lambda c: what in getattr(c, where)) if isinstance(what, str) else what
                self._cells = []
            @property
            def nb(self): return NB(self._cells)
            def on_iter(self, _, cell):
                if has_directive(cell, 'hide'): return
                if self.what(cell): self._cells.append(cell)
        nb = NB.fromStateMessage(state)
        cb = FindCB('displaydh')
        [*shortens(nb.process(cb).cells, 'r', 80)]
        ["{'idx': 1, 'cell_type': 'code', 'source': '# cell 1\\nimport time\\nfrom itertools…",
         '{\'idx\': 3, \'cell_type\': \'code\', \'source\': "# cell 3\\ndisplaydh(\'cell 3\', metadat…',
         '{\'idx\': 4, \'cell_type\': \'code\', \'source\': "# cell 4\\nimport time\\ntime.sleep(2)\\…',
         "{'idx': 5, 'cell_type': 'code', 'source': '# cell 5\\ndisplaydh(Javascript(\\'cons…",
         '{\'idx\': 7, \'cell_type\': \'code\', \'source\': "# cell 7\\ndisplaydh(HTML(\'cell 7.1\'),…',
         '{\'idx\': 16, \'cell_type\': \'code\', \'source\': "# cell 16\\ndh = displaydh(display_id…',
         '{\'idx\': 17, \'cell_type\': \'code\', \'source\': "# cell 17\\ndh = displaydh(HTML(\'cell…',
         '{\'idx\': 19, \'cell_type\': \'code\', \'source\': "# cell 19\\ndisplaydh(JSON({\'cell\': 1…',
         '{\'idx\': 24, \'cell_type\': \'code\', \'source\': "# cell 24\\nfrom itertools import cou…',
         '{\'idx\': 26, \'cell_type\': \'code\', \'source\': "# cell 26\\n_ = displaydh(\'cell 26.1\'…',
         '{\'idx\': 35, \'cell_type\': \'code\', \'source\': "# cell 35\\ndh2 = displaydh({\'applica…',
         "{'idx': 37, 'cell_type': 'code', 'source': 'from itertools import count\\nimport …",
         '{\'idx\': 39, \'cell_type\': \'code\', \'source\': "# cell 39\\ndh = displaydh(metadata={…',
         '{\'idx\': 40, \'cell_type\': \'code\', \'source\': "# cell 40\\nthis_id = next(counter)\\n…']
        list(nb.cells.filter(lambda c: 'displaydh' in c.source).map(shorten, mode='r', limit=80))
        ["{'idx': 1, 'cell_type': 'code', 'source': '# cell 1\\nimport time\\nfrom itertools…",
         '{\'idx\': 3, \'cell_type\': \'code\', \'source\': "# cell 3\\ndisplaydh(\'cell 3\', metadat…',
         '{\'idx\': 4, \'cell_type\': \'code\', \'source\': "# cell 4\\nimport time\\ntime.sleep(2)\\…',
         "{'idx': 5, 'cell_type': 'code', 'source': '# cell 5\\ndisplaydh(Javascript(\\'cons…",
         '{\'idx\': 7, \'cell_type\': \'code\', \'source\': "# cell 7\\ndisplaydh(HTML(\'cell 7.1\'),…',
         '{\'idx\': 16, \'cell_type\': \'code\', \'source\': "# cell 16\\ndh = displaydh(display_id…',
         '{\'idx\': 17, \'cell_type\': \'code\', \'source\': "# cell 17\\ndh = displaydh(HTML(\'cell…',
         '{\'idx\': 19, \'cell_type\': \'code\', \'source\': "# cell 19\\ndisplaydh(JSON({\'cell\': 1…',
         '{\'idx\': 24, \'cell_type\': \'code\', \'source\': "# cell 24\\nfrom itertools import cou…',
         '{\'idx\': 26, \'cell_type\': \'code\', \'source\': "# cell 26\\n_ = displaydh(\'cell 26.1\'…',
         '{\'idx\': 35, \'cell_type\': \'code\', \'source\': "# cell 35\\ndh2 = displaydh({\'applica…',
         "{'idx': 37, 'cell_type': 'code', 'source': 'from itertools import count\\nimport …",
         '{\'idx\': 39, \'cell_type\': \'code\', \'source\': "# cell 39\\ndh = displaydh(metadata={…',
         '{\'idx\': 40, \'cell_type\': \'code\', \'source\': "# cell 40\\nthis_id = next(counter)\\n…']
        list(nb.source.filter(lambda c: 'displaydh' in c))  # type: ignore
        ['# cell 1\nimport time\nfrom itertools import count\n\nimport ipywidgets as W\nimport matplotlib.pyplot as plt\nfrom bridget.helpers import displaydh\nfrom IPython.display import HTML, Image, Javascript, JSON, DisplayHandle, clear_output\ncounter = count()',
         "# cell 3\ndisplaydh('cell 3', metadata={'bridge': {'cell': 3}});",
         "# cell 4\nimport time\ntime.sleep(2)\ndisplaydh(HTML('cell 4'), metadata={'bridge': {'cell': 4}});",
         '# cell 5\ndisplaydh(Javascript(\'console.log("cell 5")\'), metadata={\'bridge\': {\'cell\': 5}});',
         "# cell 7\ndisplaydh(HTML('cell 7.1'), metadata={'bridge': {'cell': 7.1}})\ndisplaydh(HTML('cell 7.2'), metadata={'bridge': {'cell': 7.2}});",
         "# cell 16\ndh = displaydh(display_id=True, metadata={'bridge': {'cell': 16}})",
         "# cell 17\ndh = displaydh(HTML('cell 17'), metadata={'bridge': {'cell': 17}})",
         "# cell 19\ndisplaydh(JSON({'cell': 19}), metadata={'bridge': {'cell': 19}});",
         "# cell 24\nfrom itertools import count\nfrom bridget.helpers import displaydh\nfrom IPython.display import HTML, Javascript, clear_output\ncounter = count()\ndh0 = displaydh(HTML('cell 24.0'), metadata={'bridge': {'cell': 24.0}})\ndh1 = displaydh(\n    {'application/x-notebook-state+json': {'feedback': True, 'hide': False, 'debug': True, 'id': next(counter)}}, \n    raw=True, metadata={'bridge': {'cell': 24.1}})",
         "# cell 26\n_ = displaydh('cell 26.1', metadata={'bridge': {'cell': 26.1}})\n_ = displaydh('cell 26.2', metadata={'bridge': {'cell': 26.2}})",
         "# cell 35\ndh2 = displaydh({'application/x-notebook-state+json': {'feedback': True, 'debug': True, 'id': next(counter)}}, \n        raw=True, metadata={'bridge': {'cell': 35}})\n# clear_output()",
         'from itertools import count\nimport anywidget, time\nfrom IPython.display import DisplayHandle\nfrom bridget.helpers import displaydh\n# from bridget.helpers import skip\nimport ipywidgets as W\n\ncounter = count()\n\nclass TestWidget(anywidget.AnyWidget):\n    _esm = \'\'\'debugger;\nexport default { \n    async initialize({ model }) {\n        function on_msg(msg) {\n            console.log(`++++ Received message:`, msg);\n            if (window.$Nb) {\n                msg.origin = document.location.href;\n                window.$Nb.update(msg);\n                return;\n            }\n            return model.send({ id: msg.id, response: \'no response\' });\n        }\n        model.on("msg:custom", on_msg);\n        function on_stateChange(chg) {\n            console.log(\'++++ on_state\', chg.reqId, chg);\n            model.send({ changes: chg });\n        }\n        let cleanup;\n        if (window.$Nb) {\n            cleanup = window.$Nb.addStateObserver(on_stateChange);\n        }\n        if (cleanup) return cleanup;\n    }\n};\n    \'\'\'\n    dh: DisplayHandle\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.on_msg(self._handle_message)\n        self.out = W.Output()\n        display(self.out)\n        with self.out:\n            print(\'Test widget, cell 35\')\n\n    def _handle_message(self, w, msg, buffers):\n        # self.dh.update(f\'Received {msg=}, {buffers=}\', metadata=skip(cell=35))\n        self.msg = msg\n        with self.out:\n            print(f\'Received {msg=}, {buffers=}\')\n\nw = TestWidget()',
         "# cell 39\ndh = displaydh(metadata={'bridge': {'cell': 39}})",
         "# cell 40\nthis_id = next(counter)\n_ = displaydh(metadata={'bridge': {'cell': 40, 'this': this_id}})\n# nb.source.send({'cmd': 'get_state'}, timeout=5)\n# clear_output(wait=True)"]
        cb = FindCB('# find_me')
        c = nb.process(cb).cells[0]
        c
        NBCell@41
        • idx: 41
        • cell_type: code
        • source: # cell 41 # find_me
        • id: X56sZmlsZQ==
        • metadata: {'brd': {'id': '340489bf-419a-4da3-9b06-eb1b5cd6daba'}}
        • outputs
          • execution_count: 7
          WhereT = Literal['source', 'outputs', 'metadata', 'all']
          
          @FC.patch
          def find(self: NB, what:str|Callable[[NBCell], bool], where:WhereT='source') -> L:
              if isinstance(what, str): f = (lambda c: what in (str(getattr(c, where, '') if where != 'all' else c)))
              else: f = what
              return self.cells.filter(f)
          nb.find('# find_me')  # type: ignore
          (#1) [{'idx': 41, 'cell_type': 'code', 'source': '# cell 41\n# find_me', 'id': 'X56sZmlsZQ==', 'metadata': {'brd': {'id': '340489bf-419a-4da3-9b06-eb1b5cd6daba'}}, 'outputs': [], 'execution_count': 7}]
          if in_vscode: val_at(c, 'metadata.brd')
          c = nb.cells[4]
          c
          NBCell@4
          • idx: 4
          • cell_type: code
          • source: # cell 4 import time time.sleep(2) displaydh(HTML('cell 4'), metadata={'bridge': {'cell': 4}});
          • id: W4sZmlsZQ==
          • metadata: {'brd': {'id': '798f7f83-9b31-4e21-a36b-5520c6f72a2d'}}
          • outputs
              0
              • output_type: display_data
              • data
                • text/html: cell 4
                • text/plain: <IPython.core.display.HTML object>
              • metadata: {'bridge': {'cell': 4}}
          • execution_count: 4
          vals_at(c, 'outputs.*.data.text/plain')
          ('<IPython.core.display.HTML object>',)
          nb[2]
          NBCell@2
          • idx: 2
          • cell_type: code
          • source: # cell 2 print(1)
          • id: W2sZmlsZQ==
          • metadata: {'brd': {'id': '92f3e304-fd32-4de2-badf-11577f9e7a4a'}}
          • outputs
              0
              • output_type: stream
              • name: stdout
              • text: 1
          • execution_count: 2
          vals_at(nb.cells, '*.outputs.*.data.text/plain')
          (empty,
           empty,
           empty,
           ("'cell 3'",),
           ('<IPython.core.display.HTML object>',),
           ('<IPython.core.display.Javascript object>',),
           empty,
           ('<IPython.core.display.HTML object>', '<IPython.core.display.HTML object>'),
           ('<IPython.core.display.HTML object>',),
           ('<IPython.core.display.Javascript object>',),
           ('<IPython.core.display.Markdown object>',),
           ('<IPython.core.display.SVG object>',),
           ("IntSlider(value=12, description='cell')",),
           ('Output()',),
           ('<Figure size 400x267 with 1 Axes>',),
           ('<IPython.core.display.Image object>',),
           empty,
           ('<IPython.core.display.HTML object>',),
           empty,
           ('<IPython.core.display.JSON object>',),
           ("IntSlider(value=20, description='cell')",),
           empty,
           empty,
           empty,
           ('<IPython.core.display.HTML object>', ''),
           empty,
           ("'cell 26.1'", "'cell 26.2'"),
           ("'cell 27.1'", "'cell 27.2'"),
           empty,
           empty,
           empty,
           empty,
           empty,
           empty,
           empty,
           empty,
           empty,
           ('Output()',),
           empty,
           empty,
           empty,
           empty)
          vals_at(nb.cells, '*.source')
          ('# cell 0',
           '# cell 1\nimport time\nfrom itertools import count\n\nimport ipywidgets as W\nimport matplotlib.pyplot as plt\nfrom bridget.helpers import displaydh\nfrom IPython.display import HTML, Image, Javascript, JSON, DisplayHandle, clear_output\ncounter = count()',
           '# cell 2\nprint(1)',
           "# cell 3\ndisplaydh('cell 3', metadata={'bridge': {'cell': 3}});",
           "# cell 4\nimport time\ntime.sleep(2)\ndisplaydh(HTML('cell 4'), metadata={'bridge': {'cell': 4}});",
           '# cell 5\ndisplaydh(Javascript(\'console.log("cell 5")\'), metadata={\'bridge\': {\'cell\': 5}});',
           '# cell 6\nprint(6.1)\nprint(6.2)',
           "# cell 7\ndisplaydh(HTML('cell 7.1'), metadata={'bridge': {'cell': 7.1}})\ndisplaydh(HTML('cell 7.2'), metadata={'bridge': {'cell': 7.2}});",
           '%HTML\n<h3>cell 8</h3>',
           "%javascript\nconsole.log('cell 9')",
           '%markdown\ncell 10',
           '%SVG\n<svg width="100" height="20" xmlns="http://www.w3.org/2000/svg">\n  <text x="10" y="10">cell 11</text>\n</svg>',
           "# cell 12\nW.IntSlider(12, description='cell')",
           "#| hide\n# cell 13\nw = W.Output()\ndisplay(w)\nwith w:\n    print('cell 13.1')\n    display('cell 13.2')\n    display(HTML('cell 13.3'))",
           '# cell 14\nfig = plt.figure(figsize=(4, 2.67))\nplt.plot([1,2,3,4]);',
           "#| export\n# cell 15\nImage('https://jupyter.org/assets/try/jupyter.png', metadata={'bridge': {'cell': 15}})",
           "# cell 16\ndh = displaydh(display_id=True, metadata={'bridge': {'cell': 16}})",
           "# cell 17\ndh = displaydh(HTML('cell 17'), metadata={'bridge': {'cell': 17}})",
           "# cell 18\ndh.update(HTML('cell 18'), metadata={'bridge': {'cell': 18}})",
           "# cell 19\ndisplaydh(JSON({'cell': 19}), metadata={'bridge': {'cell': 19}});",
           "# cell 20\ndisplay(W.IntSlider(20, description='cell'), metadata={'bridge': {'cell': 20}})",
           '',
           '# cell 22\n1/0',
           '# cell 23',
           "# cell 24\nfrom itertools import count\nfrom bridget.helpers import displaydh\nfrom IPython.display import HTML, Javascript, clear_output\ncounter = count()\ndh0 = displaydh(HTML('cell 24.0'), metadata={'bridge': {'cell': 24.0}})\ndh1 = displaydh(\n    {'application/x-notebook-state+json': {'feedback': True, 'hide': False, 'debug': True, 'id': next(counter)}}, \n    raw=True, metadata={'bridge': {'cell': 24.1}})",
           "# cell 25\ndh1.update({'application/x-notebook-state+json': {'id': next(counter), 'update': 'diff'}}, raw=True, \n        metadata={'bridge': {'cell': 25}})",
           "# cell 26\n_ = displaydh('cell 26.1', metadata={'bridge': {'cell': 26.1}})\n_ = displaydh('cell 26.2', metadata={'bridge': {'cell': 26.2}})",
           "# cell 27\n_ = display('cell 27.1', metadata={'bridge': {'cell': 27.1}})\n_ = display('cell 27.2', metadata={'bridge': {'cell': 27.2}})",
           "# cell 28\ndh1.update({'application/x-notebook-state+json': {'id': next(counter)}}, raw=True, \n        metadata={'bridge': {'cell': 28}})\ndh0.update(HTML('cell 28'), metadata={'bridge': {'cell': 28, 'cnt': next(counter)}})",
           "# cell 29\ndh1.update({'application/x-notebook-state+json': {'feedback': False, 'id': next(counter), 'update':'opts'}}, raw=True, \n        metadata={'bridge': {'cell': 29}})",
           "# cell 30\ndh1.update({'application/x-notebook-state+json': {'feedback': True, 'id': next(counter), 'update':'opts'}}, raw=True, \n        metadata={'bridge': {'cell': 30}})",
           "# cell 31\ndh1.update({'application/x-notebook-state+json': {'hide': True, 'id': next(counter), 'update':'opts'}}, raw=True, \n        metadata={'bridge': {'cell': 31}})",
           "# cell 32\ndh1.update({'application/x-notebook-state+json': {'hide': False, 'id': next(counter), 'update':'opts'}}, raw=True, \n        metadata={'bridge': {'cell': 32}})",
           "# cell 33\ndh1.update({'application/x-notebook-state+json': {'debug': False, 'id': next(counter)}, 'update':'opts'}, raw=True, \n        metadata={'bridge': {'cell': 33}})",
           "# cell 34\ndh1.update({'application/x-notebook-state+json': {'debug': True, 'id': next(counter)}, 'update':'opts'}, raw=True, \n        metadata={'bridge': {'cell': 34}})",
           "# cell 35\ndh2 = displaydh({'application/x-notebook-state+json': {'feedback': True, 'debug': True, 'id': next(counter)}}, \n        raw=True, metadata={'bridge': {'cell': 35}})\n# clear_output()",
           "# cell 36\ndh2.update({'application/x-notebook-state+json': {'id': next(counter)}}, raw=True, \n        metadata={'bridge': {'cell': 36, 'update': True}})",
           'from itertools import count\nimport anywidget, time\nfrom IPython.display import DisplayHandle\nfrom bridget.helpers import displaydh\n# from bridget.helpers import skip\nimport ipywidgets as W\n\ncounter = count()\n\nclass TestWidget(anywidget.AnyWidget):\n    _esm = \'\'\'debugger;\nexport default { \n    async initialize({ model }) {\n        function on_msg(msg) {\n            console.log(`++++ Received message:`, msg);\n            if (window.$Nb) {\n                msg.origin = document.location.href;\n                window.$Nb.update(msg);\n                return;\n            }\n            return model.send({ id: msg.id, response: \'no response\' });\n        }\n        model.on("msg:custom", on_msg);\n        function on_stateChange(chg) {\n            console.log(\'++++ on_state\', chg.reqId, chg);\n            model.send({ changes: chg });\n        }\n        let cleanup;\n        if (window.$Nb) {\n            cleanup = window.$Nb.addStateObserver(on_stateChange);\n        }\n        if (cleanup) return cleanup;\n    }\n};\n    \'\'\'\n    dh: DisplayHandle\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.on_msg(self._handle_message)\n        self.out = W.Output()\n        display(self.out)\n        with self.out:\n            print(\'Test widget, cell 35\')\n\n    def _handle_message(self, w, msg, buffers):\n        # self.dh.update(f\'Received {msg=}, {buffers=}\', metadata=skip(cell=35))\n        self.msg = msg\n        with self.out:\n            print(f\'Received {msg=}, {buffers=}\')\n\nw = TestWidget()',
           "# cell 38\nw.send({'id': next(counter), 'update': 'full'})",
           "# cell 39\ndh = displaydh(metadata={'bridge': {'cell': 39}})",
           "# cell 40\nthis_id = next(counter)\n_ = displaydh(metadata={'bridge': {'cell': 40, 'this': this_id}})\n# nb.source.send({'cmd': 'get_state'}, timeout=5)\n# clear_output(wait=True)",
           '# cell 41\n# find_me')
          vals_at(nb.cells, '*.metadata.brd.id')[:10]  # type: ignore
          ('81c3e877-b59a-48f5-a1da-21894d928d4b',
           '717322f8-95fa-425c-839d-8b9e7d4ef921',
           '92f3e304-fd32-4de2-badf-11577f9e7a4a',
           'f2c19c18-a3f7-4acb-88e4-c7239178c401',
           '798f7f83-9b31-4e21-a36b-5520c6f72a2d',
           'a20081a9-4e7e-4301-be25-2a44f45bfc71',
           'e1ba8c0c-d248-44ff-9437-17482a711358',
           '7512abfe-f7d2-4047-a6b1-56aefbf9457e',
           '72d2a352-a5e3-4bb4-8e12-2302f9bac880',
           '39565bc0-3d14-4912-8220-e9dacb965ca4')
          vals_at(nb.cells, '*.outputs')[10:14]  # type: ignore
          ([{'output_type': 'display_data',
             'data': {'text/markdown': 'cell 10\n',
              'text/plain': '<IPython.core.display.Markdown object>'},
             'metadata': {}}],
           [{'output_type': 'display_data',
             'data': {'image/svg+xml': '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="20">\n  <text x="10" y="10">cell 11</text>\n</svg>',
              'text/plain': '<IPython.core.display.SVG object>'},
             'metadata': {'__displayOpenPlotIcon': True}}],
           [{'output_type': 'execute_result',
             'data': {'application/vnd.jupyter.widget-view+json': {'version_major': 2,
               'version_minor': 0,
               'model_id': '6191b18d61a44fbd89eb132d22a28eab'},
              'text/plain': "IntSlider(value=12, description='cell')"},
             'execution_count': 12,
             'metadata': {}}],
           [{'output_type': 'display_data',
             'data': {'application/vnd.jupyter.widget-view+json': {'version_major': 2,
               'version_minor': 0,
               'model_id': 'a9408d195fb84649b38948893390ef10'},
              'text/plain': 'Output()'},
             'metadata': {}}])

          find

          L(vals_at(nb, '*.outputs.*.data.application/json')).argwhere(lambda x: x is not empty)
          (#1) [19]
          L(vals_at(nb, '*.outputs.*.name')).argwhere(lambda x: x is not empty)
          (#2) [2,6]
          test_eq(_there('outputs.*.data', 'stdout', op.contains, nb.cells[7]), False)
          for idx in L(vals_at(nb, '*.outputs.*.name')).argwhere(lambda x: x is not empty):
              test_eq(_there('outputs.0.name', 'stdout', op.contains, nb[idx]), True)
          for idx in L(vals_at(nb, '*.metadata.brd.renderer')).argwhere(lambda x: x is not empty):
              test_eq(_there('metadata.brd.renderer', True, op.is_, nb[idx]), True)
          test_eq(any(_there('source', '# find_me', op.contains, c) for c in nb), True)

          source

          show_doc

           show_doc (sym, renderer=None, name:str|None=None, title_level:int=3)

          Show signature and docstring for sym

          Type Default Details
          sym Symbol to document
          renderer NoneType None Optional renderer (defaults to markdown)
          name str | None None Optionally override displayed name of sym
          title_level int 3 Heading level to use for symbol name
          nbp = nb.process(slc=slice(31, None))
          # nbp.find('# find_me').attrgot('source').map(shorten, mode='r')
          vals_at(nbp.find('# find_me'), '*.source')
          ('# cell 41\n# find_me',)
          nb.find(True, 'metadata.brd.renderer', op.is_).attrgot('metadata')
          (#2) [{'brd': {'id': 'e4bbb456-27fa-47d1-b95b-637b61e0e8f5', 'renderer': True}},{'brd': {'id': 'e7eb193d-f9fe-41b6-b817-1328963ff734', 'renderer': True}}]
          nb.find('stdout', 'outputs.0.name').attrgot('source')
          (#2) ['# cell 2\nprint(1)','# cell 6\nprint(6.1)\nprint(6.2)']
          nb.find('stdout', 'outputs.*.name').attrgot('source')
          (#2) ['# cell 2\nprint(1)','# cell 6\nprint(6.1)\nprint(6.2)']

          found

          @FC.patch
          def found(self: NB, what:str|Callable[[NBCell], bool], where:WhereT='source', cbs:Callback|Sequence[Callback]=()) -> NB:
              return self.process(cbs or FindCB(what, where))
          
          nb.found('# find_me').cells  # type: ignore
          (#1) [{'idx': 41, 'cell_type': 'code', 'source': '# cell 41\n# find_me', 'id': 'X56sZmlsZQ==', 'metadata': {'brd': {'id': '340489bf-419a-4da3-9b06-eb1b5cd6daba'}}, 'outputs': [], 'execution_count': 7}]

          source

          show_doc

           show_doc (sym, renderer=None, name:str|None=None, title_level:int=3)

          Show signature and docstring for sym

          Type Default Details
          sym Symbol to document
          renderer NoneType None Optional renderer (defaults to markdown)
          name str | None None Optionally override displayed name of sym
          title_level int 3 Heading level to use for symbol name
          nb.found('# find_me').cells.attrgot('source')
          (#1) ['# cell 41\n# find_me']
          nb.found('#| hide').cells
          (#1) [{'idx': 13, 'cell_type': 'code', 'source': "#| hide\n# cell 13\nw = W.Output()\ndisplay(w)\nwith w:\n    print('cell 13.1')\n    display('cell 13.2')\n    display(HTML('cell 13.3'))", 'id': 'X16sZmlsZQ==', 'metadata': {'brd': {'id': '8af15850-3d11-4498-a037-ce8b1ac2a161'}}, 'outputs': [{'output_type': 'display_data', 'data': {'application/vnd.jupyter.widget-view+json': {'version_major': 2, 'version_minor': 0, 'model_id': 'a9408d195fb84649b38948893390ef10'}, 'text/plain': 'Output()'}, 'metadata': {}}], 'execution_count': 13}]
          class StripDirectives(Callback):
              @property
              def nb(self): return self._nb
              def before_iter(self, istat): self._nb = NB.from_NB(istat.context, [])
              def on_iter(self, _, cell):
                  self._nb.cells.append(c := cell.copy())
                  extract_directives(c)
          
          display([*shortens(nb.found('#| hide').source, 'r')])
          display([*shortens(nb.found('#| hide', cbs=StripDirectives()).source, 'r')])
          ['#| hide\n# cell 13\nw = W.Output()\ndisplay…']
          ['# cell 13\nw = W.Output()\ndisplay(w)\nwith…']
          def strip_nbdev_dirs_(nb:NB):
              f = FC.compose(copycell, TZ.curried.do(extract_directives))
              return NB.from_NB(nb, nb.cells.map(f))
          
          list(shortens(nb.found('#| hide').pipe((strip_nbdev_dirs_,)).source, 'r'))
          ['# cell 13\nw = W.Output()\ndisplay(w)\nwith…']