Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion aidialog/_modidx.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@
'aidialog.dialog._code_span': ('dialog.html#_code_span', 'aidialog/dialog.py'),
'aidialog.dialog._fmt_param': ('dialog.html#_fmt_param', 'aidialog/dialog.py'),
'aidialog.dialog._get_exported': ('dialog.html#_get_exported', 'aidialog/dialog.py'),
'aidialog.dialog._get_mexp': ('dialog.html#_get_mexp', 'aidialog/dialog.py'),
'aidialog.dialog._latex_parts': ('dialog.html#_latex_parts', 'aidialog/dialog.py'),
'aidialog.dialog._set_exported': ('dialog.html#_set_exported', 'aidialog/dialog.py'),
'aidialog.dialog._set_mexp': ('dialog.html#_set_mexp', 'aidialog/dialog.py'),
'aidialog.dialog.add_id_hash': ('dialog.html#add_id_hash', 'aidialog/dialog.py'),
'aidialog.dialog.ai_fmt': ('dialog.html#ai_fmt', 'aidialog/dialog.py'),
'aidialog.dialog.code_output': ('dialog.html#code_output', 'aidialog/dialog.py'),
Expand Down
21 changes: 12 additions & 9 deletions aidialog/dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,15 +482,18 @@ def directives(self:Message):
return mk_cell(self.content, metadata=self.meta).directives

def _get_exported(self): return 'export' in self.directives or 'exports' in self.directives
def _set_exported(self, v):
c = mk_cell(self.content, metadata=self.meta)
d = c.directives
val = d.get('export', d.get('exports'))
c.directives = {k:x for k,x in d.items() if k not in ('export','exports')}
if self.content != c.source: self.content = c.source
if v: self.meta.setdefault('nbdev',{})['export'] = val or 'true'
Message.exported = property(_get_exported, _set_exported,
doc="Whether this message carries an nbdev export directive, in content or meta; assigning writes the meta form, migrating any content directive")
Message.exported = property(_get_exported,
doc="Whether this message carries an nbdev export directive, in content or meta (read-only: edit content, or assign `meta_exported`)")

def _get_mexp(self): return any(k in self.meta.get('nbdev',{}) for k in ('export','exports'))
def _set_mexp(self, v):
if v: self.meta.setdefault('nbdev',{})['export'] = 'true'
else:
nbd = self.meta.get('nbdev',{})
for k in ('export','exports'): nbd.pop(k, None)
if not nbd: self.meta.pop('nbdev', None)
Message.meta_exported = property(_get_mexp, _set_mexp,
doc="The meta `nbdev` export entry alone - the host-owned switch; assigning writes or clears only meta, never content")

def dlg2py(dlg):
"The exported code of `dlg`, as a python source string"
Expand Down
39 changes: 20 additions & 19 deletions nbs/01_dialog.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,7 @@
"id": "59fcb413",
"metadata": {},
"source": [
"A message is exported when it carries an nbdev `export` directive - either a `#| export` comment in the content, or an `export` entry in the meta `nbdev` dict. The `directives` property merges both sources with comments winning, matching nbdev's own rule, so `exported` and every consumer of it see one answer. Assigning `exported` writes the canonical meta form: turning it on sets `meta['nbdev']['export']` and removes any content directive line (so re-toggling a message migrates it), turning it off clears both locations - no partial state survives a toggle. `dlg2py` joins a dialog's exported code into a python source string - the projection behind \"export to .py\" features."
"A message is exported when it carries an nbdev `export` directive - either a `#| export` comment in the content, or an `export` entry in the meta `nbdev` dict. The `directives` property merges both sources with comments winning, matching nbdev's own rule, so `exported` and every consumer of it see one answer. `exported` is read-only, because the two sources have different owners: a content directive is text the user owns and edits directly, while `meta_exported` is the host's own read-write switch - assigning it writes or clears only `meta['nbdev']`, never touching content. `dlg2py` joins a dialog's exported code into a python source string - the projection behind \"export to .py\" features."
]
},
{
Expand All @@ -1538,15 +1538,18 @@
" return mk_cell(self.content, metadata=self.meta).directives\n",
"\n",
"def _get_exported(self): return 'export' in self.directives or 'exports' in self.directives\n",
"def _set_exported(self, v):\n",
" c = mk_cell(self.content, metadata=self.meta)\n",
" d = c.directives\n",
" val = d.get('export', d.get('exports'))\n",
" c.directives = {k:x for k,x in d.items() if k not in ('export','exports')}\n",
" if self.content != c.source: self.content = c.source\n",
" if v: self.meta.setdefault('nbdev',{})['export'] = val or 'true'\n",
"Message.exported = property(_get_exported, _set_exported,\n",
" doc=\"Whether this message carries an nbdev export directive, in content or meta; assigning writes the meta form, migrating any content directive\")\n",
"Message.exported = property(_get_exported,\n",
" doc=\"Whether this message carries an nbdev export directive, in content or meta (read-only: edit content, or assign `meta_exported`)\")\n",
"\n",
"def _get_mexp(self): return any(k in self.meta.get('nbdev',{}) for k in ('export','exports'))\n",
"def _set_mexp(self, v):\n",
" if v: self.meta.setdefault('nbdev',{})['export'] = 'true'\n",
" else:\n",
" nbd = self.meta.get('nbdev',{})\n",
" for k in ('export','exports'): nbd.pop(k, None)\n",
" if not nbd: self.meta.pop('nbdev', None)\n",
"Message.meta_exported = property(_get_mexp, _set_mexp,\n",
" doc=\"The meta `nbdev` export entry alone - the host-owned switch; assigning writes or clears only meta, never content\")\n",
"\n",
"def dlg2py(dlg):\n",
" \"The exported code of `dlg`, as a python source string\"\n",
Expand All @@ -1566,19 +1569,17 @@
"e3 = xd.mk_message('def h(): pass', msg_type=scode, meta={'nbdev': {'export': 'true'}})\n",
"xd.mk_message('#| export\\nexported note', msg_type=snote)\n",
"test_eq([m.exported for m in xd.messages], [True, False, True, True]) # comment, none, meta, comment\n",
"test_eq([m.meta_exported for m in xd.messages], [False, False, True, False]) # the switch sees only meta\n",
"test_eq(e1.directives, {'export': ''})\n",
"e2.exported = True # new exports go to meta, not content\n",
"e2.meta_exported = True # the switch writes meta, not content\n",
"test_eq((e2.content, e2.meta), ('def g(): pass', {'nbdev': {'export': 'true'}}))\n",
"test_eq(dlg2py(xd), '#| export\\ndef f(): pass\\n\\ndef g(): pass\\n\\ndef h(): pass') # code only\n",
"e2.exported = False # off clears meta\n",
"e2.meta_exported = False # off clears meta only\n",
"test_eq((e2.exported, e2.meta), (False, {}))\n",
"e1.exported = True # True on a comment-exported message migrates the directive to meta\n",
"test_eq((e1.content, e1.meta), ('def f(): pass', {'nbdev': {'export': 'true'}}))\n",
"e1.exported = False\n",
"test_eq((e1.exported, e1.content, e1.meta), (False, 'def f(): pass', {}))\n",
"em = xd.mk_message('#|exports: mymod\\ndef i(): pass', msg_type=scode)\n",
"em.exported = True # migration keeps the directive's value, whatever its spelling\n",
"test_eq((em.content, em.meta), ('def i(): pass', {'nbdev': {'export': 'mymod'}}))"
"e1.meta_exported = True # a comment-exported message gains the meta form too; content untouched\n",
"test_eq((e1.content, e1.meta), ('#| export\\ndef f(): pass', {'nbdev': {'export': 'true'}}))\n",
"e1.meta_exported = False # still exported: the comment is text the user owns\n",
"test_eq((e1.exported, e1.meta_exported, e1.content, e1.meta), (True, False, '#| export\\ndef f(): pass', {}))"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion nbs/03_dlgskill.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@
"xd = Dialog(name='exports')\n",
"exp1 = xd.mk_message('#| export\\ndef f(): pass', msg_type=scode)\n",
"exp2 = xd.mk_message('def g(): pass', msg_type=scode)\n",
"exp2.exported = True\n",
"exp2.meta_exported = True\n",
"deep = xd.mk_message('## Deep\\nbody under the heading', msg_type=snote)\n",
"test_eq(xd.find_msgs(only_exp=True, context=0), [exp1, exp2])\n",
"test_eq(xd.find_msgs(header_section='Deep', context=0), [deep]) # matched on the first line only\n",
Expand Down
Loading