question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Preserve front matter ordering

See original GitHub issue

It’s a tricky thing to do with PyYAML, but using http://stackoverflow.com/a/21048064/5483904 it’s possible. Once you fix the loader up, the things that stand in the way are:

  • parse takes in defaults as **kwargs, which is automatically a dict. Additionally, you can’t specify a custom loader, so you have to set it globally.
  • Once you fix that, Post.__init__ takes the metadata as **kwargs yet again, which destroys the ordered dict received by the prior function

I suspect to really do this, one would have to break backwards compat. Here’s my hacky way of accomplishing this in case anyone else wants this Right Now:

#  Patch yaml first

import collections
import yaml

_mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG

def dict_representer(dumper, data):
    return dumper.represent_dict(data.items())

def dict_constructor(loader, node):
    loader.flatten_mapping(node)
    return collections.OrderedDict(loader.construct_pairs(node))

try:
    yaml.CSafeDumper.add_representer(collections.OrderedDict, dict_representer)
except ImportError:
    pass

yaml.SafeDumper.add_representer(collections.OrderedDict, dict_representer)
yaml.SafeLoader.add_constructor(_mapping_tag, dict_constructor)

# patch frontmatter second
import frontmatter

def _parse(text, **defaults):
    text = frontmatter.u(text)

    # metadata starts with defaults
    metadata = defaults.copy()

    try:
        _, fm, content = frontmatter.FM_BOUNDARY.split(text, 2)
    except ValueError:
        return metadata, text

    fm = yaml.safe_load(fm)

    if isinstance(fm, dict):
        fm.update(metadata)
        metadata = fm

    return metadata, content.strip()

def _loads(text, **defaults):
    metadata, content = _parse(text, **defaults)
    post = frontmatter.Post(content)
    post.metadata = metadata
    return post

frontmatter.parse = _parse
frontmatter.loads = _loads

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:2
  • Comments:14 (4 by maintainers)

github_iconTop GitHub Comments

10reactions
dirkcuyscommented, Feb 11, 2020

I’ve managed to get order preserving frontmatter! The quick version is:

  1. upgrade to python >= 3.7
  2. Add sort_keys=False to frontmatter.dump ie frontmatter.dump(post, f, sort_keys=False)

Since python 3.7 insertion order for dicts are maintained (no OrderedDict needed) and since then PyYaml have added the option to not sort keys when dumping. kwargs is passed to handler.export, which is passed to yaml.dump and things just work!

1reaction
eyeseastcommented, Jul 30, 2018

I’m happy if anyone has a PR that can solve this. For anything in the core library, updates should be added at the handler level.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Best Practices: Front Matter for eBooks by Section
There aren't any definitive rules for how the different sections of front matter in an eBook should be organized, and it is very...
Read more >
Book front matter elements - Book Design Made Simple
The usual order of book front matter elements · Half (or “bastard”) title page · Frontispiece · Title page (required) · Copyright page...
Read more >
Create and Edit Front Matter - Pressbooks User Guide
Add a number to the Order input in Front Matter Attributes to control its ... Click the 'Save' button. ... Understand Front Matter...
Read more >
The Front Matter: A Breakdown | Book Design
The “front matter” of a book includes the title page, copyright page, dedication, table of contents, foreword or preface, and introduction.
Read more >
Front Matter and Back Matter [The Only Guide You Need]
“Front matter” and “back matter” are terms used to describe the first and last pages of a book (but not the actual story...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found