Edit Front Matter Module¶
- Synopsis
A thread safe class that uses Jinja2 templating to edit yaml front matter within text files. This class is intended to be used for batch processing.
- Platform
Unix, Windows, python >=v3.5.3
- Dependencies
Jinja2>=2.10.1 MarkupSafe>=1.1.1 oyaml>=0.9 PyYAML>=5.1
- License
- Module Author
- Current Release
version: 0.0.1
New in version 0.0.1: Initial Version
-
exception
EditFrontMatter_Exception
(msg, exc, *args, **kwargs)[source] Bases:
Exception
Custom exception handler for EditFrontMatter Project
-
__init__
(msg, exc, *args, **kwargs)[source]
-
-
class
EditFrontMatter
(*, file_path=None, jinja2_env=<jinja2.environment.Environment object>, template_str='', yaml_delim='---', keys_toDelete=[], do_readFile=True)[source] Bases:
object
Main Class for module
-
__init__
(*, file_path=None, jinja2_env=<jinja2.environment.Environment object>, template_str='', yaml_delim='---', keys_toDelete=[], do_readFile=True)[source] Main class for the module. Programmatically Adds / Updates / Deletes yaml front matter elements embedded in text/markdown files.
Hint
This class uses keyword only arguments. Inheriting this class would look something like the following:
class Derived_EditFrontMatter (EditFrontMatter): def __init__(self,**kwargs): EditFrontMatter.__init__(self, **kwargs)
- Parameters
yaml_delim (str) – yaml file section delimiter (i.e. “—”)used to locate the source file’s embedded yaml section.
do_readFile (bool) – allow instantiation without implicit
readFile()
call
- Variables
self.file_lines (list) – Lines from the data source file. Must be managed after creating the class object if __init__(do_readFile=False)
self.file_path (str) – Path of source data file. Superfluous if
readFile()
is never calledself.fmatter (yaml) – [default: empty
dict
if yaml not found] Front matter as a yaml object. Set inreadFile()
.self.yaml_delim (str) – [default:”—”] Front matter delimiter. Can be used to change front matter delimter between reading the source file into
file_lines
and executingdumpFrontMatter()
/writeFile()
.self.yamlSeperator_pattern (
re.compile()
) – Regex patten for the yaml line delimiter. only used ifreadFile()
is calledself.yaml_start (int) – Beginning of the yaml blob in the original source file. Set in
readFile()
self.yaml_end (int) – End of the yaml blob in the origional source file. Set in
readFile()
self.template_str (str) – Contains the jinja2 template. Can be manipulated between class instantiation and executing
run()
self.jinja2_env (jinja2.Environment) – This object can be specified during class instantiation if greater control is required
self.keys_toDelete (list) – keys to be deleted from
fmatter
object. Utilized at the end of therun()
method
- Throws:
-
set_yaml_delim
(delim, *args, **kwargs) → None[source] Set the yaml delimiter and compile it.
- Parameters
delim (str) – A string to use as a delimiter for finding and editing frontmatter in a file.
-
readFile
(file_path=None, *args, **kwargs) → None[source] - Read a file into
file_lines
list (if applicable) and seperate the front matter into
fmatter
yaml object. This function resetsfmatter
.
- Parameters
file_path (str) – optional file path
Hint
If local file_path:None and
file_path
:None,file_lines
should be populated before calling this function.In the example below, the initialization would fail if do_readFile:True:
proc = EditFrontMatter(do_readFile=False) proc.file_lines = ''.join(open(RUN_PATH + "example.md", "r").readlines()) # initialize proc.fmatter and record data position proc.readFile() ...
Note
If the file source content is empty
file_empty
is set to True. This affectsdumpFileData()
andwriteFile()
behavior- Read a file into
-
writeFile
(file_path=None, *args, **kwargs) → bool[source] Write to arg file_path, attr
file_path
Note
If the original file source data was empty after a call to
readFile()
, no attempt is maid to write to the file.- Parameters
file_path (str) – optional file path
- Returns
True if file was written
’False` if file was not written
-
add_JinjaFilter
(name, func, *args, **kwargs) → None[source] - Add a Jinja filter
for setting a jinja2 template variable programmatically through callback.
- Parameters
- Example of implementing a filter for callback
Programatically change the value of draft field in the source document example1.md using a Jinja2 filter
- jinja2 template
{% set toc = "true" %} toc: {{ toc }} draft: {{ false | canPublish }} hasMath: {{ hasMath }} stuff: {{ addedVariable }}
- mardown file
--- title: "EditFrontMatter Class Example 1" description: "Edit some fields in this front matter" catagories: [programming, python, markdown] deleteme: this will be deleted tags: [front matter, administration, testing] # comments and spaces will be eliminated (see docs) author: "Karl N. Redman" creatordisplayname: "Karl N. Redman" creatoremail: "karl.redman@example.com" date: 2019-05-23T17:43:45-05:00 lastmodifierdisplayname: "Karl N. Redman" lastmodifieremail: "karl.redman@gmail.com" lastmod: 2019-05-23T17:43:45-05:00 toc: false type: "page" hasMath: false draft: false weight: 5 --- # EditFontMatter Class Example 1 Edit several fields of front matter. ## Fields affected in this example: * toc * note: uses local template variable * pre: false * post: true * draft: * note: uses jinja2 filter (callback) * pre: false * post: true * hasMath * note: uses program variable * pre: true * post: false * stuff: * note: uses program variable to create field * pre: did not exist * post: (list) ['one', 'two', 'three'] * deleteme: * note: removed from final result * pre: this will be deleted * post: N/A
- Example code
from editfrontmatter import EditFrontMatter import os # a jinja2 filter callback function def canPublish_func(val): # do some processing.... return True # stringify the template file template_str = ''.join(open(os.environ.get("TEST_DATA_DIR") + "template1.j2", "r").readlines()) # creating object obj = EditFrontMatter(file_path = os.environ.get("TEST_DATA_DIR") + "example1.md", template_str = template_str) # set `canPublish_func` function for our `draft` field callback using # `canPublish` template variable. obj.add_JinjaFilter('canPublish', canPublish_func) # process the front matter from 'example1.md'. `draft` in the front # matter will be set to `true` obj.run() # print the new file contents (uncomment to see dump) # print(obj.dumpFileData())
-
del_JinjaFilter
(name, *args, **kwargs) → bool[source] Delete a Jinja filter.
- Parameters
name (str) – filter key
- Returns
True if filter found and deleted
False if filter not found
-
dumpFrontMatter
(*args, **kwargs) → str[source] Dump fmatter as a string
- Returns
fmatter
content as a string
-
dumpFileData
(*args, **kwargs) → str[source] Concatenate frontmatter with original content and return as a string.
- Returns
A string formed by the concatination of
fmatter
andfile_lines
(if file souce content is not empty* and yaml was present).An empty string if file source content is empty or original yaml was not present.
Hint
fmatter
andfile_lines
are still available if needed beyond this method. One way of managing this data would be to manually prepend yaml front matter tofile_lines
and rerunreadFile()
before calling this function again.
-
has_source_yaml
() → bool[source] Checks if the yaml is empty after a call to
readFile()
Note
This return value does not rely on
fmatter
since that attribute is subject to change oncereadFile()
is called.- Returns
True if the original source file data did have a yaml section
False if the original source file data did not have a yaml section
-
has_source_data
() → bool[source] Checks if the source file data is empty
- Returns
True if the source data content is empty
False if the source data is not empty
-
run
(extraVars_dict={}, *args, **kwargs) → None[source] Process the front matter changes and delete previously specified yaml keys.
Variables to change yaml data are passed as a dictionary argument as extraVars_dict.
- Parameters
extraVars_dict (dict) – key,value pairs to be set or added in the
fmatter
object.
Example
Call EditFrontMatter.run() with variables to change in
fmatter
:proc = EditFrontMatter() ... proc.run({'hasMath': True, 'addedVariable': ['one', 'two', 'three']}) ...
-