qBFj%UdZddlmZddlZddlZddlZddlmZddlm Z m Z m Z de d<de d <d e d < dd lm Zdd lmZn#e$rddlmZddlmZYnwxYw ddlZn #e$rdZYnwxYwddlmZe rddlmZgdZereddZGddZGddeZGddeZerGddeZdSdZde d<dS)ad .. testsetup:: handlers import frontmatter By default, ``frontmatter`` reads and writes YAML metadata. But maybe you don't like YAML. Maybe enjoy writing metadata in JSON, or TOML, or some other exotic markup not yet invented. For this, there are handlers. This module includes handlers for YAML, JSON and TOML, as well as a :py:class:`BaseHandler ` that outlines the basic API and can be subclassed to deal with new formats. **Note**: The TOML handler is only available if the `toml `_ library is installed. Handlers -------- Handlers do most of the underlying work parsing and exporting front matter. When you call :py:func:`frontmatter.loads `, frontmatter first needs to figure out the best handler for the format you're using (YAML, JSON, TOML, etc), then call methods to read or write metadata. A handler needs to do four things: - detect whether it can parse the given piece of text - split front matter from content, returning both as a two-tuple - parse front matter into a Python dictionary - export a dictionary back into text An example: Calling :py:func:`frontmatter.load ` (or :py:func:`loads `) with the ``handler`` argument tells frontmatter which handler to use. The handler instance gets saved as an attribute on the returned post object. By default, calling :py:func:`frontmatter.dumps ` on the post will use the attached handler. :: >>> import frontmatter >>> from frontmatter.default_handlers import YAMLHandler, TOMLHandler >>> post = frontmatter.load('tests/toml/hello-toml.md', handler=TOMLHandler()) >>> post.handler #doctest: +ELLIPSIS >>> print(frontmatter.dumps(post)) # doctest: +SKIP +++ test = "tester" something = "else" author = "bob" +++ Title ===== title2 ------ Hello. Just need three dashes --- And this shouldn't break. Passing a new handler to :py:func:`frontmatter.dumps ` (or :py:func:`dump `) changes the export format: :: >>> print(frontmatter.dumps(post, handler=YAMLHandler())) # doctest: +NORMALIZE_WHITESPACE --- author: bob something: else test: tester --- Title ===== title2 ------ Hello. Just need three dashes --- And this shouldn't break. Changing the attached ``handler`` on a post has the same effect. Setting ``handler`` to ``None`` will default the post back to :py:class:`YAMLHandler `. These three variations will produce the same export: :: # set YAML format when dumping, but the old handler attached >>> t1 = frontmatter.dumps(post, handler=YAMLHandler()) >>> post.handler = YAMLHandler() # set a new handler, changing all future exports >>> t2 = frontmatter.dumps(post) >>> post.handler = None # remove handler, defaulting back to YAML >>> t3 = frontmatter.dumps(post) >>> t1 == t2 == t3 True All handlers use the interface defined on ``BaseHandler``. Each handler needs to know how to: - split metadata and content, based on a boundary pattern (``handler.split``) - parse plain text metadata into a Python dictionary (``handler.load``) - export a dictionary back into plain text (``handler.export``) - format exported metadata and content into a single string (``handler.format``) ) annotationsN) ModuleType) TYPE_CHECKINGAnyTypez*Type[yaml.CDumper] | Type[yaml.SafeDumper] SafeDumperz.Type[yaml.CSafeLoader] | Type[yaml.SafeLoader] SafeLoaderzModuleType | Nonetoml) CSafeDumper) CSafeLoader)r)r )u)Post) BaseHandler YAMLHandler JSONHandler TOMLHandlerz8{start_delimiter} {metadata} {end_delimiter} {content} cveZdZUdZdZded<dZded<dZded< ddd Zd dZ d!dZ d"dZ d#dZ d$dZ dS)%rz BaseHandler lays out all the steps to detecting, splitting, parsing and exporting front matter metadata. All default handlers are subclassed from BaseHandler. Nre.Pattern[str] | None FM_BOUNDARY str | NoneSTART_DELIMITER END_DELIMITER fm_boundarystart_delimiter end_delimiterc|p|j|_|p|j|_|p|j|_|j,td|jjdS)NzRNo frontmatter boundary defined. Please set {}.FM_BOUNDARY to a regular expression)rrrNotImplementedErrorformat __class____name__)selfrrrs JC:\PYTHON\_runtimes\venv\Lib\site-packages\frontmatter/default_handlers.py__init__zBaseHandler.__init__sv ':$*:.F$2F*@d.@   #%DDJFN+EE  $ #textstrreturnboolcP|jJ|j|rdSdS)a Decide whether this handler can parse the given ``text``, and return True or False. Note that this is *not* called when passing a handler instance to :py:func:`frontmatter.load ` or :py:func:`loads `. NTF)rmatch)r"r&s r#detectzBaseHandler.detects6+++   ! !$ ' ' 4ur%tuple[str, str]cZ|jJ|j|d\}}}||fS)z9 Split text into frontmatter and content Nrsplitr"r&_fmcontents r#r1zBaseHandler.splits;+++)//a882w7{r%r4dict[str, Any]ct)z5 Parse frontmatter and return a dict r)r"r4s r#loadzBaseHandler.load "!r%metadatadict[str, object]kwargsobjectc t)z. Turn metadata back into text r8)r"r;r=s r#exportzBaseHandler.exportr:r%postrc |d|j}|d|j}|j|jfi|}t ||j||S)zJ Turn a post into a string, used in ``frontmatter.dumps`` rr)r;r5rr) poprrr@r;DEFAULT_POST_TEMPLATErr5strip)r"rAr=rrr;s r#rzBaseHandler.formats!**%68LMM ?D4FGG 4;t}7777$++L+' ,  %''  r%)NNN)rrrrrr)r&r'r(r)r&r'r(r-)r4r'r(r6r;r<r=r>r(r')rArr=r>r(r')r! __module__ __qualname____doc__r__annotations__rrr$r,r1r9r@rr%r#rrs+/K...."&O&&&& $M$$$$/3&*$( $    """" """" r%rcVeZdZdZejdejZdxZZ dd Z dd Z dS)rz Load and export YAML metadata. By default, this handler uses YAML's "safe" mode, though it's possible to override that. z ^-{3,}\s*$z---r4r'r=r>r(rc \|dttj|fi|S)zP Parse YAML front matter. This uses yaml.SafeLoader by default. Loader) setdefaultr yamlr9r"r4r=s r#r9zYAMLHandler.loads2 (J///y&&v&&&r%r;r<c |dt|dd|ddtj|fi|}t |S)zP Export metadata as YAML. This uses yaml.SafeDumper by default. Dumperdefault_flow_styleF allow_unicodeT)rPrrQdumprErr"r;r= metadata_strs r#r@zYAMLHandler.exportsv (J///.666/4000y44V44::<< r%Nr4r'r=r>r(rrG r!rHrIrJrecompile MULTILINErrrr9r@rLr%r#rrsg "*]BL99K&++Om''''      r%rc^eZdZdZejdejZdZdZ ddZ dd Z ddZ dS)rz Load and export JSON metadata. Note that changing ``START_DELIMITER`` or ``END_DELIMITER`` may break JSON parsing. z ^(?:{|})$r&r'r(r-cf|jJ|j|d\}}}d|zdz|fS)Nr/{}r0r2s r#r1zJSONHandler.splitsB+++)//a882wRx#~w&&r%r4r=r>rc &tj|fi|SN)jsonloadsrRs r#r9zJSONHandler.load"sz"'''''r%r;r<c p|ddtj|fi|}t|S)zTurn metadata into JSONindent)rPrfdumpsrrXs r#r@zJSONHandler.export%s;(A&&&z(55f55 r%NrFrZrG) r!rHrIrJr\r]r^rrrr1r9r@rLr%r#rrs{ "*\2<88KOM'''' ((((r%rcVeZdZdZejdejZdxZZ dd Z dd Z dS)rz] Load and export TOML metadata. By default, split based on ``+++``. z ^\+{3,}\s*$z+++r4r'r=r>r(rc 8tJtj|fi|Sre)r rgrRs r#r9zTOMLHandler.load8s&###:b++F++ +r%r;r<c ZtJtj|}t|S)zTurn metadata into TOML)r rkrrXs r#r@zTOMLHandler.export<s)###:h//L\?? "r%NrZrGr[rLr%r#rr.sg  !bj>> *//- , , , , # # # # # #r%zType[TOMLHandler] | None)rJ __future__rrfr\rQtypesrtypingrrrrKr rr r ImportErrorr utilr frontmatterr__all__appendrDrrrrrLr%r#rws{tttj#""""" ++++++++++6666:::: .............    KKKK DDD!       8 7 7" NN=!!!MMMMMMMM`+8+41#####k#####*-1K000000s# AAAA A*)A*