Skip to content

Commit b40f832

Browse files
committed
fixes #788
1 parent 180c3bb commit b40f832

3 files changed

Lines changed: 54 additions & 9 deletions

File tree

fastcore/_modidx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@
761761
'fastcore.xtras.flexicache': ('xtras.html#flexicache', 'fastcore/xtras.py'),
762762
'fastcore.xtras.flexiclass': ('xtras.html#flexiclass', 'fastcore/xtras.py'),
763763
'fastcore.xtras.friendly_name': ('xtras.html#friendly_name', 'fastcore/xtras.py'),
764+
'fastcore.xtras.frontmatter': ('xtras.html#frontmatter', 'fastcore/xtras.py'),
764765
'fastcore.xtras.get_source_link': ('xtras.html#get_source_link', 'fastcore/xtras.py'),
765766
'fastcore.xtras.globtastic': ('xtras.html#globtastic', 'fastcore/xtras.py'),
766767
'fastcore.xtras.hl_md': ('xtras.html#hl_md', 'fastcore/xtras.py'),

fastcore/xtras.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
'detect_mime', 'bunzip', 'loads', 'loads_multi', 'dumps', 'untar_dir', 'repo_details', 'shell', 'ssh',
1111
'rsync_multi', 'run', 'open_file', 'save_pickle', 'load_pickle', 'parse_env', 'expand_wildcards',
1212
'atomic_save', 'dict2obj', 'obj2dict', 'repr_dict', 'is_listy', 'mapped', 'IterLen', 'ReindexCollection',
13-
'SaveReturn', 'trim_wraps', 'save_iter', 'asave_iter', 'clean_cli_output', 'unqid', 'rtoken_hex',
14-
'friendly_name', 'n_friendly_names', 'exec_eval', 'get_source_link', 'sparkline', 'modify_exception',
15-
'round_multiple', 'set_num_threads', 'join_path_file', 'autostart', 'EventTimer', 'stringfmt_names',
16-
'PartialFormatter', 'partial_format', 'truncstr', 'utc2local', 'local2utc', 'trace', 'modified_env',
17-
'ContextManagers', 'shufflish', 'console_help', 'hl_md', 'type2str', 'dataclass_src', 'Unset', 'nullable_dc',
18-
'make_nullable', 'flexiclass', 'asdict', 'vars_pub', 'is_typeddict', 'is_namedtuple', 'CachedIter',
19-
'CachedAwaitable', 'reawaitable', 'is_async_callable', 'maybe_await', 'noopa', 'flexicache', 'time_policy',
20-
'mtime_policy', 'timed_cache']
13+
'SaveReturn', 'trim_wraps', 'save_iter', 'asave_iter', 'frontmatter', 'clean_cli_output', 'unqid',
14+
'rtoken_hex', 'friendly_name', 'n_friendly_names', 'exec_eval', 'get_source_link', 'sparkline',
15+
'modify_exception', 'round_multiple', 'set_num_threads', 'join_path_file', 'autostart', 'EventTimer',
16+
'stringfmt_names', 'PartialFormatter', 'partial_format', 'truncstr', 'utc2local', 'local2utc', 'trace',
17+
'modified_env', 'ContextManagers', 'shufflish', 'console_help', 'hl_md', 'type2str', 'dataclass_src',
18+
'Unset', 'nullable_dc', 'make_nullable', 'flexiclass', 'asdict', 'vars_pub', 'is_typeddict', 'is_namedtuple',
19+
'CachedIter', 'CachedAwaitable', 'reawaitable', 'is_async_callable', 'maybe_await', 'noopa', 'flexicache',
20+
'time_policy', 'mtime_policy', 'timed_cache']
2121

2222
# %% ../nbs/03_xtras.ipynb #3401d507
2323
from .imports import *
@@ -596,6 +596,17 @@ def asave_iter(g):
596596
def _(*args, **kwargs): return _save_iter(g, *args, **kwargs)
597597
return _
598598

599+
# %% ../nbs/03_xtras.ipynb #20e906c7
600+
def frontmatter(txt:str)->dict:
601+
"Dict contained in frontmatter in `txt`, if present"
602+
import yaml
603+
if not txt.startswith('---\n'): return {}
604+
fm,part,_ = txt[4:].partition('\n---\n')
605+
if not part: return {}
606+
try: res = yaml.safe_load(fm)
607+
except yaml.parser.ParserError: return {}
608+
return res if isinstance(res,dict) else {}
609+
599610
# %% ../nbs/03_xtras.ipynb #45eb5141
600611
def clean_cli_output(txt:str, strip:bool=True):
601612
"Clean CLI output by handling alternate screen, carriage returns, and ANSI escapes"

nbs/03_xtras.ipynb

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2345,7 +2345,7 @@
23452345
{
23462346
"data": {
23472347
"text/plain": [
2348-
"['g', 'f', 'b', 'a', 'e', 'c', 'd', 'h']"
2348+
"['f', 'h', 'g', 'e', 'd', 'b', 'a', 'c']"
23492349
]
23502350
},
23512351
"execution_count": null,
@@ -2705,6 +2705,39 @@
27052705
"## Other Helpers"
27062706
]
27072707
},
2708+
{
2709+
"cell_type": "code",
2710+
"execution_count": null,
2711+
"id": "20e906c7",
2712+
"metadata": {},
2713+
"outputs": [],
2714+
"source": [
2715+
"#| export\n",
2716+
"def frontmatter(txt:str)->dict:\n",
2717+
" \"Dict contained in frontmatter in `txt`, if present\"\n",
2718+
" import yaml\n",
2719+
" if not txt.startswith('---\\n'): return {}\n",
2720+
" fm,part,_ = txt[4:].partition('\\n---\\n')\n",
2721+
" if not part: return {}\n",
2722+
" try: res = yaml.safe_load(fm)\n",
2723+
" except yaml.parser.ParserError: return {}\n",
2724+
" return res if isinstance(res,dict) else {}"
2725+
]
2726+
},
2727+
{
2728+
"cell_type": "code",
2729+
"execution_count": null,
2730+
"id": "b8165cbd",
2731+
"metadata": {},
2732+
"outputs": [],
2733+
"source": [
2734+
"test_eq(frontmatter('---\\ntitle: \"Hi there\"\\ntags: [a,b]\\n---\\nBody'), {'title':'Hi there', 'tags':['a','b']})\n",
2735+
"test_eq(frontmatter('---\\nbroken: [a,'), {})\n",
2736+
"test_eq(frontmatter('No frontmatter here'), {})\n",
2737+
"test_eq(frontmatter('---\\njust text no closing'), {})\n",
2738+
"test_eq(frontmatter('---\\n---\\nBody'), {})"
2739+
]
2740+
},
27082741
{
27092742
"cell_type": "code",
27102743
"execution_count": null,

0 commit comments

Comments
 (0)