python-frontmatter 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {python_frontmatter-1.2.0/python_frontmatter.egg-info → python_frontmatter-1.3.0}/PKG-INFO +32 -32
  2. {python_frontmatter-1.2.0 → python_frontmatter-1.3.0}/README.md +11 -2
  3. python_frontmatter-1.3.0/pyproject.toml +50 -0
  4. python_frontmatter-1.2.0/MANIFEST.in +0 -7
  5. python_frontmatter-1.2.0/PKG-INFO +0 -170
  6. python_frontmatter-1.2.0/python_frontmatter.egg-info/SOURCES.txt +0 -41
  7. python_frontmatter-1.2.0/python_frontmatter.egg-info/dependency_links.txt +0 -1
  8. python_frontmatter-1.2.0/python_frontmatter.egg-info/not-zip-safe +0 -1
  9. python_frontmatter-1.2.0/python_frontmatter.egg-info/requires.txt +0 -12
  10. python_frontmatter-1.2.0/python_frontmatter.egg-info/top_level.txt +0 -1
  11. python_frontmatter-1.2.0/setup.cfg +0 -4
  12. python_frontmatter-1.2.0/setup.py +0 -51
  13. python_frontmatter-1.2.0/tests/empty/empty-frontmatter.result.json +0 -3
  14. python_frontmatter-1.2.0/tests/empty/empty-frontmatter.txt +0 -4
  15. python_frontmatter-1.2.0/tests/empty/no-frontmatter.result.json +0 -3
  16. python_frontmatter-1.2.0/tests/empty/no-frontmatter.txt +0 -1
  17. python_frontmatter-1.2.0/tests/json/hello-json.md +0 -18
  18. python_frontmatter-1.2.0/tests/json/hello-json.result.json +0 -6
  19. python_frontmatter-1.2.0/tests/stub_tests.py +0 -21
  20. python_frontmatter-1.2.0/tests/test_docs.py +0 -17
  21. python_frontmatter-1.2.0/tests/test_files.py +0 -46
  22. python_frontmatter-1.2.0/tests/toml/hello-toml.md +0 -18
  23. python_frontmatter-1.2.0/tests/toml/hello-toml.result.json +0 -6
  24. python_frontmatter-1.2.0/tests/unit_test.py +0 -398
  25. python_frontmatter-1.2.0/tests/yaml/chinese.result.json +0 -5
  26. python_frontmatter-1.2.0/tests/yaml/chinese.txt +0 -6
  27. python_frontmatter-1.2.0/tests/yaml/extra-dash.result.json +0 -5
  28. python_frontmatter-1.2.0/tests/yaml/extra-dash.txt +0 -6
  29. python_frontmatter-1.2.0/tests/yaml/extra-space.result.json +0 -5
  30. python_frontmatter-1.2.0/tests/yaml/extra-space.txt +0 -6
  31. python_frontmatter-1.2.0/tests/yaml/hello-markdown.md +0 -18
  32. python_frontmatter-1.2.0/tests/yaml/hello-markdown.result.json +0 -6
  33. python_frontmatter-1.2.0/tests/yaml/hello-world.result.json +0 -5
  34. python_frontmatter-1.2.0/tests/yaml/hello-world.txt +0 -6
  35. python_frontmatter-1.2.0/tests/yaml/network-diagrams.md +0 -12
  36. python_frontmatter-1.2.0/tests/yaml/network-diagrams.result.json +0 -9
  37. python_frontmatter-1.2.0/tests/yaml/unpretty.md +0 -21
  38. python_frontmatter-1.2.0/tests/yaml/unpretty.result.json +0 -23
  39. {python_frontmatter-1.2.0 → python_frontmatter-1.3.0}/LICENSE +0 -0
  40. {python_frontmatter-1.2.0 → python_frontmatter-1.3.0}/frontmatter/__init__.py +0 -0
  41. {python_frontmatter-1.2.0 → python_frontmatter-1.3.0}/frontmatter/conftest.py +0 -0
  42. {python_frontmatter-1.2.0 → python_frontmatter-1.3.0}/frontmatter/default_handlers.py +0 -0
  43. {python_frontmatter-1.2.0 → python_frontmatter-1.3.0}/frontmatter/py.typed +0 -0
  44. {python_frontmatter-1.2.0 → python_frontmatter-1.3.0}/frontmatter/util.py +0 -0
@@ -1,50 +1,41 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-frontmatter
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: Parse and manage posts with YAML (or other) frontmatter
5
- Home-page: https://github.com/eyeseast/python-frontmatter
6
- Author: Chris Amico
7
- Author-email: eyeseast@gmail.com
8
- License: MIT
9
5
  Keywords: frontmatter
6
+ Author: Chris Amico
7
+ Author-email: Chris Amico <eyeseast@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
10
  Classifier: Development Status :: 5 - Production/Stable
11
11
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
12
  Classifier: Natural Language :: English
14
13
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.9
16
14
  Classifier: Programming Language :: Python :: 3.10
17
15
  Classifier: Programming Language :: Python :: 3.11
18
16
  Classifier: Programming Language :: Python :: 3.12
19
17
  Classifier: Programming Language :: Python :: 3.13
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: PyYAML
23
- Provides-Extra: test
24
- Requires-Dist: pytest; extra == "test"
25
- Requires-Dist: toml; extra == "test"
26
- Requires-Dist: pyaml; extra == "test"
27
- Requires-Dist: mypy; extra == "test"
28
- Requires-Dist: types-PyYAML; extra == "test"
29
- Requires-Dist: types-toml; extra == "test"
18
+ Requires-Dist: pyyaml
19
+ Requires-Dist: sphinx ; extra == 'docs'
20
+ Requires-Dist: pytest ; extra == 'test'
21
+ Requires-Dist: toml ; extra == 'test'
22
+ Requires-Dist: pyaml ; extra == 'test'
23
+ Requires-Dist: mypy ; extra == 'test'
24
+ Requires-Dist: types-pyyaml ; extra == 'test'
25
+ Requires-Dist: types-toml ; extra == 'test'
26
+ Requires-Dist: toml ; extra == 'toml'
27
+ Requires-Python: >=3.10
28
+ Project-URL: repository, https://github.com/eyeseast/python-frontmatter
29
+ Project-URL: issues, https://github.com/eyeseast/python-frontmatter/issues
30
+ Project-URL: documentation, http://python-frontmatter.rtfd.io
30
31
  Provides-Extra: docs
31
- Requires-Dist: sphinx; extra == "docs"
32
- Dynamic: author
33
- Dynamic: author-email
34
- Dynamic: classifier
35
- Dynamic: description
36
- Dynamic: description-content-type
37
- Dynamic: home-page
38
- Dynamic: keywords
39
- Dynamic: license
40
- Dynamic: license-file
41
- Dynamic: provides-extra
42
- Dynamic: requires-dist
43
- Dynamic: summary
32
+ Provides-Extra: test
33
+ Provides-Extra: toml
34
+ Description-Content-Type: text/markdown
44
35
 
45
36
  # Python Frontmatter
46
37
 
47
- [Jekyll](http://jekyllrb.com/)-style YAML front matter offers a useful way to add arbitrary, structured metadata to text documents, regardless of type.
38
+ [Front matter](https://docs.github.com/en/contributing/writing-for-github-docs/using-yaml-frontmatter) offers a useful way to add arbitrary, structured metadata to text documents, regardless of type.
48
39
 
49
40
  This is a small package to load and parse files (or just text) with YAML (or JSON, TOML or other) front matter.
50
41
 
@@ -55,7 +46,16 @@ This is a small package to load and parse files (or just text) with YAML (or JSO
55
46
 
56
47
  ## Install:
57
48
 
58
- pip install python-frontmatter
49
+ ```shell
50
+ # with pip
51
+ pip install python-frontmatter
52
+
53
+ # or uv
54
+ uv add python-frontmatter
55
+
56
+ # local development, with uv
57
+ uv sync
58
+ ```
59
59
 
60
60
  ## Usage:
61
61
 
@@ -1,6 +1,6 @@
1
1
  # Python Frontmatter
2
2
 
3
- [Jekyll](http://jekyllrb.com/)-style YAML front matter offers a useful way to add arbitrary, structured metadata to text documents, regardless of type.
3
+ [Front matter](https://docs.github.com/en/contributing/writing-for-github-docs/using-yaml-frontmatter) offers a useful way to add arbitrary, structured metadata to text documents, regardless of type.
4
4
 
5
5
  This is a small package to load and parse files (or just text) with YAML (or JSON, TOML or other) front matter.
6
6
 
@@ -11,7 +11,16 @@ This is a small package to load and parse files (or just text) with YAML (or JSO
11
11
 
12
12
  ## Install:
13
13
 
14
- pip install python-frontmatter
14
+ ```shell
15
+ # with pip
16
+ pip install python-frontmatter
17
+
18
+ # or uv
19
+ uv add python-frontmatter
20
+
21
+ # local development, with uv
22
+ uv sync
23
+ ```
15
24
 
16
25
  ## Usage:
17
26
 
@@ -0,0 +1,50 @@
1
+ [project]
2
+ name = "python-frontmatter"
3
+ version = "1.3.0"
4
+ description = "Parse and manage posts with YAML (or other) frontmatter"
5
+ readme = "README.md"
6
+ authors = [{ name = "Chris Amico", email = "eyeseast@gmail.com" }]
7
+ requires-python = ">=3.10"
8
+ dependencies = ["PyYAML"]
9
+ license = "MIT"
10
+ license-files = ["LICENSE"]
11
+ keywords = ["frontmatter"]
12
+ classifiers = [
13
+ "Development Status :: 5 - Production/Stable",
14
+ "Intended Audience :: Developers",
15
+ "Natural Language :: English",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ ]
22
+ [project.urls]
23
+ repository = "https://github.com/eyeseast/python-frontmatter"
24
+ issues = "https://github.com/eyeseast/python-frontmatter/issues"
25
+ documentation = "http://python-frontmatter.rtfd.io"
26
+
27
+ [project.optional-dependencies]
28
+ test = ["pytest", "toml", "pyaml", "mypy", "types-PyYAML", "types-toml"]
29
+ docs = ["sphinx"]
30
+ toml = ["toml"]
31
+
32
+ [dependency-groups]
33
+ dev = [
34
+ "pytest",
35
+ "toml",
36
+ "pyaml",
37
+ "mypy",
38
+ "types-PyYAML",
39
+ "types-toml",
40
+ "sphinx",
41
+ ]
42
+
43
+
44
+ [build-system]
45
+ requires = ["uv_build>=0.11.15,<0.12"]
46
+ build-backend = "uv_build"
47
+
48
+ [tool.uv.build-backend]
49
+ module-root = ""
50
+ module-name = "frontmatter"
@@ -1,7 +0,0 @@
1
- include LICENSE
2
- include README.md
3
- include frontmatter/py.typed
4
-
5
- recursive-include tests *
6
-
7
- exclude *.py[co]
@@ -1,170 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: python-frontmatter
3
- Version: 1.2.0
4
- Summary: Parse and manage posts with YAML (or other) frontmatter
5
- Home-page: https://github.com/eyeseast/python-frontmatter
6
- Author: Chris Amico
7
- Author-email: eyeseast@gmail.com
8
- License: MIT
9
- Keywords: frontmatter
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Natural Language :: English
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Programming Language :: Python :: 3.13
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: PyYAML
23
- Provides-Extra: test
24
- Requires-Dist: pytest; extra == "test"
25
- Requires-Dist: toml; extra == "test"
26
- Requires-Dist: pyaml; extra == "test"
27
- Requires-Dist: mypy; extra == "test"
28
- Requires-Dist: types-PyYAML; extra == "test"
29
- Requires-Dist: types-toml; extra == "test"
30
- Provides-Extra: docs
31
- Requires-Dist: sphinx; extra == "docs"
32
- Dynamic: author
33
- Dynamic: author-email
34
- Dynamic: classifier
35
- Dynamic: description
36
- Dynamic: description-content-type
37
- Dynamic: home-page
38
- Dynamic: keywords
39
- Dynamic: license
40
- Dynamic: license-file
41
- Dynamic: provides-extra
42
- Dynamic: requires-dist
43
- Dynamic: summary
44
-
45
- # Python Frontmatter
46
-
47
- [Jekyll](http://jekyllrb.com/)-style YAML front matter offers a useful way to add arbitrary, structured metadata to text documents, regardless of type.
48
-
49
- This is a small package to load and parse files (or just text) with YAML (or JSON, TOML or other) front matter.
50
-
51
- [![Tests](https://github.com/eyeseast/python-frontmatter/workflows/Test/badge.svg)](https://github.com/eyeseast/python-frontmatter/actions?query=workflow%3ATest)
52
- [![PyPI](https://img.shields.io/pypi/v/python-frontmatter.svg)](https://pypi.org/project/python-frontmatter/)
53
-
54
- **[Documentation](https://python-frontmatter.readthedocs.io/en/latest/)**
55
-
56
- ## Install:
57
-
58
- pip install python-frontmatter
59
-
60
- ## Usage:
61
-
62
- ```python
63
- >>> import frontmatter
64
-
65
- ```
66
-
67
- Load a post from a filename:
68
-
69
- ```python
70
- >>> post = frontmatter.load('tests/yaml/hello-world.txt')
71
-
72
- ```
73
-
74
- Or a file (or file-like object):
75
-
76
- ```python
77
- >>> with open('tests/yaml/hello-world.txt') as f:
78
- ... post = frontmatter.load(f)
79
-
80
- ```
81
-
82
- Or load from text:
83
-
84
- ```python
85
- >>> with open('tests/yaml/hello-world.txt') as f:
86
- ... post = frontmatter.loads(f.read())
87
-
88
- ```
89
-
90
- If the file has a [Byte-Order Mark](https://en.wikipedia.org/wiki/Byte_order_mark) (BOM), strip it off first. An easy way to do this is by using the [`utf-8-sig`](https://docs.python.org/3/library/codecs.html?highlight=utf%208%20sig#module-encodings.utf_8_sig) encoding:
91
-
92
- ```python
93
- >>> with open('tests/yaml/hello-world.txt', encoding="utf-8-sig") as f:
94
- ... post = frontmatter.load(f)
95
-
96
- ```
97
-
98
- Access content:
99
-
100
- ```python
101
- >>> print(post.content)
102
- Well, hello there, world.
103
-
104
- # this works, too
105
- >>> print(post)
106
- Well, hello there, world.
107
-
108
- ```
109
-
110
- Use metadata (metadata gets proxied as post keys):
111
-
112
- ```python
113
- >>> print(post['title'])
114
- Hello, world!
115
-
116
- ```
117
-
118
- Metadata is a dictionary, with some handy proxies:
119
-
120
- ```python
121
- >>> sorted(post.keys())
122
- ['layout', 'title']
123
-
124
- >>> from pprint import pprint
125
- >>> post['excerpt'] = 'tl;dr'
126
- >>> pprint(post.metadata)
127
- {'excerpt': 'tl;dr', 'layout': 'post', 'title': 'Hello, world!'}
128
-
129
- ```
130
-
131
- If you don't need the whole post object, just parse:
132
-
133
- ```python
134
- >>> with open('tests/yaml/hello-world.txt') as f:
135
- ... metadata, content = frontmatter.parse(f.read())
136
- >>> print(metadata['title'])
137
- Hello, world!
138
-
139
- ```
140
-
141
- Write back to plain text, too:
142
-
143
- ```python
144
- >>> print(frontmatter.dumps(post)) # doctest: +NORMALIZE_WHITESPACE
145
- ---
146
- excerpt: tl;dr
147
- layout: post
148
- title: Hello, world!
149
- ---
150
- Well, hello there, world.
151
-
152
- ```
153
-
154
- Or write to a file (or file-like object):
155
-
156
- ```python
157
- >>> from io import StringIO
158
- >>> f = StringIO()
159
- >>> frontmatter.dump(post, f)
160
- >>> print(f.getvalue()) # doctest: +NORMALIZE_WHITESPACE
161
- ---
162
- excerpt: tl;dr
163
- layout: post
164
- title: Hello, world!
165
- ---
166
- Well, hello there, world.
167
-
168
- ```
169
-
170
- For more examples, see files in the `tests/` directory. Each sample file has a corresponding `.result.json` file showing the expected parsed output. See also the `examples/` directory, which covers more ways to customize input and output.
@@ -1,41 +0,0 @@
1
- LICENSE
2
- MANIFEST.in
3
- README.md
4
- setup.py
5
- frontmatter/__init__.py
6
- frontmatter/conftest.py
7
- frontmatter/default_handlers.py
8
- frontmatter/py.typed
9
- frontmatter/util.py
10
- python_frontmatter.egg-info/PKG-INFO
11
- python_frontmatter.egg-info/SOURCES.txt
12
- python_frontmatter.egg-info/dependency_links.txt
13
- python_frontmatter.egg-info/not-zip-safe
14
- python_frontmatter.egg-info/requires.txt
15
- python_frontmatter.egg-info/top_level.txt
16
- tests/stub_tests.py
17
- tests/test_docs.py
18
- tests/test_files.py
19
- tests/unit_test.py
20
- tests/empty/empty-frontmatter.result.json
21
- tests/empty/empty-frontmatter.txt
22
- tests/empty/no-frontmatter.result.json
23
- tests/empty/no-frontmatter.txt
24
- tests/json/hello-json.md
25
- tests/json/hello-json.result.json
26
- tests/toml/hello-toml.md
27
- tests/toml/hello-toml.result.json
28
- tests/yaml/chinese.result.json
29
- tests/yaml/chinese.txt
30
- tests/yaml/extra-dash.result.json
31
- tests/yaml/extra-dash.txt
32
- tests/yaml/extra-space.result.json
33
- tests/yaml/extra-space.txt
34
- tests/yaml/hello-markdown.md
35
- tests/yaml/hello-markdown.result.json
36
- tests/yaml/hello-world.result.json
37
- tests/yaml/hello-world.txt
38
- tests/yaml/network-diagrams.md
39
- tests/yaml/network-diagrams.result.json
40
- tests/yaml/unpretty.md
41
- tests/yaml/unpretty.result.json
@@ -1,12 +0,0 @@
1
- PyYAML
2
-
3
- [docs]
4
- sphinx
5
-
6
- [test]
7
- pytest
8
- toml
9
- pyaml
10
- mypy
11
- types-PyYAML
12
- types-toml
@@ -1,4 +0,0 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
-
4
- try:
5
- from setuptools import setup
6
- except ImportError:
7
- from distutils.core import setup
8
-
9
-
10
- with open("README.md") as f:
11
- readme = f.read()
12
-
13
-
14
- VERSION = "1.2.0"
15
-
16
-
17
- setup(
18
- name="python-frontmatter",
19
- version=VERSION,
20
- description="Parse and manage posts with YAML (or other) frontmatter",
21
- long_description=readme,
22
- long_description_content_type="text/markdown",
23
- author="Chris Amico",
24
- author_email="eyeseast@gmail.com",
25
- url="https://github.com/eyeseast/python-frontmatter",
26
- packages=["frontmatter"],
27
- package_data={"frontmatter": ["py.typed"]},
28
- include_package_data=True,
29
- install_requires=["PyYAML"],
30
- extras_require={
31
- "test": ["pytest", "toml", "pyaml", "mypy", "types-PyYAML", "types-toml"],
32
- "docs": ["sphinx"],
33
- },
34
- tests_require=["python-frontmatter[test]"],
35
- license="MIT",
36
- zip_safe=False,
37
- keywords="frontmatter",
38
- classifiers=[
39
- "Development Status :: 5 - Production/Stable",
40
- "Intended Audience :: Developers",
41
- "License :: OSI Approved :: MIT License",
42
- "Natural Language :: English",
43
- "Programming Language :: Python :: 3",
44
- "Programming Language :: Python :: 3.9",
45
- "Programming Language :: Python :: 3.10",
46
- "Programming Language :: Python :: 3.11",
47
- "Programming Language :: Python :: 3.12",
48
- "Programming Language :: Python :: 3.13",
49
- ],
50
- test_suite="test",
51
- )
@@ -1,3 +0,0 @@
1
- {
2
- "content": "I have frontmatter but no metadata."
3
- }
@@ -1,4 +0,0 @@
1
- ---
2
- ---
3
-
4
- I have frontmatter but no metadata.
@@ -1,3 +0,0 @@
1
- {
2
- "content": "I have no frontmatter."
3
- }
@@ -1 +0,0 @@
1
- I have no frontmatter.
@@ -1,18 +0,0 @@
1
- {
2
- "test": "tester",
3
- "author": "bob",
4
- "something": "else"
5
- }
6
-
7
- Title
8
- =====
9
-
10
- title2
11
- ------
12
-
13
- Hello.
14
-
15
- Just need three dashes
16
- ---
17
-
18
- And this might break.
@@ -1,6 +0,0 @@
1
- {
2
- "test": "tester",
3
- "author": "bob",
4
- "something": "else",
5
- "content": "Title\n=====\n\ntitle2\n------\n\nHello.\n\nJust need three dashes\n---\n\nAnd this might break."
6
- }
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env python
2
- """
3
- Generate result files for test content. Won't overwrite any that exist.
4
- """
5
- import json
6
- from pathlib import Path
7
-
8
- import frontmatter
9
- from test_files import files, get_result_filename
10
-
11
-
12
- def main():
13
- for path in files():
14
- result = Path(get_result_filename(path))
15
- if not result.exists():
16
- post = frontmatter.loads(path.read_text())
17
- result.write_text(json.dumps(post.to_dict(), indent=2), "utf-8")
18
-
19
-
20
- if __name__ == "__main__":
21
- main()
@@ -1,17 +0,0 @@
1
- # all the doctests here
2
- import doctest
3
- import frontmatter
4
-
5
-
6
- def test_readme():
7
- doctest.testfile("../README.md", extraglobs={"frontmatter": frontmatter})
8
-
9
-
10
- def test_api_docs():
11
- doctest.testmod(frontmatter, extraglobs={"frontmatter": frontmatter})
12
-
13
-
14
- def test_handler_docs():
15
- doctest.testmod(
16
- frontmatter.default_handlers, extraglobs={"frontmatter": frontmatter}
17
- )
@@ -1,46 +0,0 @@
1
- """
2
- Test individual files with frontmatter against expected results.
3
- Files should be in a subdirectory under `tests`, usually sorted by format (yaml, toml, json).
4
-
5
- For a file called hello-world.markdown, there should be a corresponding file called hello-world.result.json
6
- matching the expected output.
7
- """
8
- import os
9
- import json
10
- from itertools import chain
11
- from pathlib import Path
12
-
13
- import frontmatter
14
- import pytest
15
-
16
-
17
- def files():
18
- tests = Path(__file__).parent
19
- md = tests.glob("**/*.md")
20
- txt = tests.glob("**/*.txt")
21
- return chain(md, txt)
22
-
23
-
24
- def get_result_filename(path):
25
- root, _ = os.path.splitext(path)
26
- return f"{root}.result.json"
27
-
28
-
29
- @pytest.mark.parametrize("filename", list(files()))
30
- def test_can_parse(filename):
31
- "Check we can load every file in our test directories without raising an error"
32
- for filename in files():
33
- post = frontmatter.load(filename)
34
- assert isinstance(post, frontmatter.Post)
35
-
36
-
37
- @pytest.mark.parametrize("filename", list(files()))
38
- def test_file(filename):
39
- result = Path(get_result_filename(filename))
40
- if not result.exists():
41
- pytest.fail(f"{result.name} does not exist")
42
-
43
- post = frontmatter.load(filename)
44
- result = json.loads(result.read_text())
45
-
46
- assert post.to_dict() == result
@@ -1,18 +0,0 @@
1
- +++
2
- author = "bob"
3
- something = "else"
4
- test = "tester"
5
- +++
6
-
7
- Title
8
- =====
9
-
10
- title2
11
- ------
12
-
13
- Hello.
14
-
15
- Just need three dashes
16
- ---
17
-
18
- And this shouldn't break.
@@ -1,6 +0,0 @@
1
- {
2
- "author": "bob",
3
- "something": "else",
4
- "test": "tester",
5
- "content": "Title\n=====\n\ntitle2\n------\n\nHello.\n\nJust need three dashes\n---\n\nAnd this shouldn't break."
6
- }
@@ -1,398 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
-
4
-
5
- import codecs
6
- import doctest
7
- import glob
8
- import json
9
- import os
10
- import shutil
11
- import sys
12
- import tempfile
13
- import textwrap
14
- import unittest
15
-
16
- import frontmatter
17
- from frontmatter.default_handlers import YAMLHandler, JSONHandler, TOMLHandler
18
-
19
- try:
20
- import pyaml
21
- except ImportError:
22
- pyaml = None
23
- try:
24
- import toml
25
- except ImportError:
26
- toml = None
27
-
28
-
29
- class FrontmatterTest(unittest.TestCase):
30
- """
31
- Tests for parsing various kinds of content and metadata
32
- """
33
-
34
- maxDiff = None
35
-
36
- def test_with_markdown_content(self):
37
- "Parse frontmatter and only the frontmatter"
38
- post = frontmatter.load("tests/yaml/hello-markdown.md")
39
-
40
- metadata = {"author": "bob", "something": "else", "test": "tester"}
41
- for k, v in metadata.items():
42
- self.assertEqual(post[k], v)
43
-
44
- def test_unicode_post(self):
45
- "Ensure unicode is parsed correctly"
46
- chinese = frontmatter.load("tests/yaml/chinese.txt", "utf-8")
47
- output = frontmatter.dumps(chinese)
48
- zh = "中文"
49
-
50
- self.assertTrue(isinstance(chinese.content, str))
51
-
52
- # check that we're dumping out unicode metadata, too
53
- self.assertTrue(zh in output)
54
-
55
- # this shouldn't work as ascii, because it's Hanzi
56
- self.assertRaises(UnicodeEncodeError, chinese.content.encode, "ascii")
57
-
58
- def test_check_no_frontmatter(self):
59
- "Checks if a file does not have a frontmatter"
60
- ret = frontmatter.check("tests/empty/no-frontmatter.txt")
61
-
62
- self.assertEqual(ret, False)
63
-
64
- def test_check_empty_frontmatter(self):
65
- "Checks if a file has a frontmatter (empty or not)"
66
- ret = frontmatter.check("tests/empty/empty-frontmatter.txt")
67
-
68
- self.assertEqual(ret, True)
69
-
70
- def test_no_frontmatter(self):
71
- "This is not a zen exercise."
72
- post = frontmatter.load("tests/empty/no-frontmatter.txt")
73
- with codecs.open("tests/empty/no-frontmatter.txt", "r", "utf-8") as f:
74
- content = f.read().strip()
75
-
76
- self.assertEqual(post.metadata, {})
77
- self.assertEqual(post.content, content)
78
-
79
- def test_empty_frontmatter(self):
80
- "Frontmatter, but no metadata"
81
- post = frontmatter.load("tests/empty/empty-frontmatter.txt")
82
- content = "I have frontmatter but no metadata."
83
-
84
- self.assertEqual(post.metadata, {})
85
- self.assertEqual(post.content, content)
86
-
87
- def test_extra_space(self):
88
- "Extra space in frontmatter delimiter"
89
- post = frontmatter.load("tests/yaml/extra-space.txt")
90
- content = "This file has an extra space on the opening line of the frontmatter."
91
-
92
- self.assertEqual(post.content, content)
93
- metadata = {"something": "else", "test": "tester"}
94
- for k, v in metadata.items():
95
- self.assertEqual(post[k], v)
96
-
97
- def test_to_dict(self):
98
- "Dump a post as a dict, for serializing"
99
- post = frontmatter.load("tests/yaml/network-diagrams.md")
100
- post_dict = post.to_dict()
101
-
102
- for k, v in post.metadata.items():
103
- self.assertEqual(post_dict[k], v)
104
-
105
- self.assertEqual(post_dict["content"], post.content)
106
-
107
- def test_to_string(self):
108
- "Calling str(post) returns post.content"
109
- post = frontmatter.load("tests/yaml/hello-world.txt")
110
-
111
- # test unicode and bytes
112
- text = "Well, hello there, world."
113
- self.assertEqual(str(post), text)
114
- self.assertEqual(bytes(post), text.encode("utf-8"))
115
-
116
- def test_pretty_dumping(self):
117
- "Use pyaml to dump nicer"
118
- if pyaml is not None:
119
- with codecs.open("tests/yaml/unpretty.md", "r", "utf-8") as f:
120
- data = f.read()
121
-
122
- post = frontmatter.load("tests/yaml/unpretty.md")
123
- yaml = pyaml.dump(post.metadata)
124
-
125
- # the unsafe dumper gives you nicer output, for times you want that
126
- dump = frontmatter.dumps(post, Dumper=pyaml.PYAMLDumper)
127
-
128
- self.assertTrue(yaml in dump)
129
- self.assertEqual(dump, data)
130
-
131
- def test_with_crlf_string(self):
132
- markdown_bytes = b'---\r\ntitle: "my title"\r\ncontent_type: "post"\r\npublished: no\r\n---\r\n\r\nwrite your content in markdown here'
133
- loaded = frontmatter.loads(markdown_bytes, "utf-8")
134
- self.assertEqual(loaded["title"], "my title")
135
-
136
- def test_dumping_with_custom_delimiters(self):
137
- "dump with custom delimiters"
138
- post = frontmatter.load("tests/yaml/hello-world.txt")
139
- dump = frontmatter.dumps(post, start_delimiter="+++", end_delimiter="+++")
140
-
141
- self.assertTrue("+++" in dump)
142
-
143
- def test_dump_to_file(self):
144
- "dump post to filename"
145
- post = frontmatter.load("tests/yaml/hello-world.txt")
146
-
147
- tempdir = tempfile.mkdtemp()
148
- filename = os.path.join(tempdir, "hello.md")
149
- frontmatter.dump(post, filename)
150
-
151
- with open(filename) as f:
152
- self.assertEqual(f.read(), frontmatter.dumps(post))
153
-
154
- # cleanup
155
- shutil.rmtree(tempdir)
156
-
157
-
158
- class HandlerTest(unittest.TestCase):
159
- """
160
- Tests for custom handlers and formatting
161
- """
162
-
163
- TEST_FILES = {
164
- "tests/yaml/hello-world.txt": YAMLHandler,
165
- "tests/json/hello-json.md": JSONHandler,
166
- "tests/toml/hello-toml.md": TOMLHandler,
167
- }
168
-
169
- def sanity_check(self, filename, handler_type):
170
- "Ensure we can load -> dump -> load"
171
- post = frontmatter.load(filename)
172
-
173
- self.assertIsInstance(post.handler, handler_type)
174
-
175
- # dump and reload
176
- repost = frontmatter.loads(frontmatter.dumps(post))
177
-
178
- self.assertEqual(post.metadata, repost.metadata)
179
- self.assertEqual(post.content, repost.content)
180
- self.assertEqual(post.handler, repost.handler)
181
-
182
- def test_detect_format(self):
183
- "detect format based on default handlers"
184
-
185
- for filename, Handler in self.TEST_FILES.items():
186
- with codecs.open(filename, "r", "utf-8") as f:
187
- format = frontmatter.detect_format(f.read(), frontmatter.handlers)
188
- self.assertIsInstance(format, Handler)
189
-
190
- def test_sanity_all(self):
191
- "Run sanity check on all handlers"
192
- for filename, Handler in self.TEST_FILES.items():
193
- self.sanity_check(filename, Handler)
194
-
195
- def test_no_handler(self):
196
- "default to YAMLHandler when no handler is attached"
197
- post = frontmatter.load("tests/yaml/hello-world.txt")
198
- del post.handler
199
-
200
- text = frontmatter.dumps(post)
201
- self.assertIsInstance(
202
- frontmatter.detect_format(text, frontmatter.handlers), YAMLHandler
203
- )
204
-
205
- def test_custom_handler(self):
206
- "allow caller to specify a custom delimiter/handler"
207
-
208
- # not including this in the regular test directory
209
- # because it would/should be invalid per the defaults
210
- custom = textwrap.dedent(
211
- """
212
- ...
213
- dummy frontmatter
214
- ...
215
- dummy content
216
- """
217
- )
218
-
219
- # and a custom handler that really doesn't do anything
220
- class DummyHandler(object):
221
- def load(self, fm):
222
- return {"value": fm}
223
-
224
- def split(self, text):
225
- return "dummy frontmatter", "dummy content"
226
-
227
- # but we tell frontmatter that it is the appropriate handler
228
- # for the '...' delimiter
229
- # frontmatter.handlers['...'] = DummyHandler()
230
- post = frontmatter.loads(custom, handler=DummyHandler())
231
-
232
- self.assertEqual(post["value"], "dummy frontmatter")
233
-
234
- def test_toml(self):
235
- "load toml frontmatter"
236
- if toml is None:
237
- return
238
- post = frontmatter.load("tests/toml/hello-toml.md")
239
- metadata = {"author": "bob", "something": "else", "test": "tester"}
240
- for k, v in metadata.items():
241
- self.assertEqual(post[k], v)
242
-
243
- def test_json(self):
244
- "load raw JSON frontmatter"
245
- post = frontmatter.load("tests/json/hello-json.md")
246
- metadata = {"author": "bob", "something": "else", "test": "tester"}
247
- for k, v in metadata.items():
248
- self.assertEqual(post[k], v)
249
-
250
-
251
- class HandlerBaseTest:
252
- """
253
- Tests for frontmatter.handlers
254
- """
255
-
256
- def setUp(self):
257
- """
258
- This method should be overridden to initalize the TestCase
259
- """
260
- self.handler = None
261
- self.data = {
262
- "filename": "tests/yaml/hello-world.txt",
263
- "content": """\
264
- """,
265
- "metadata": {},
266
- }
267
-
268
- def read_from_tests(self):
269
- with open(self.data["filename"]) as f:
270
- return f.read()
271
-
272
- def test_external(self):
273
- filename = self.data["filename"]
274
- content = self.data["content"]
275
- metadata = self.data["metadata"]
276
-
277
- post = frontmatter.load(filename)
278
-
279
- self.assertEqual(post.content, content.strip())
280
- for k, v in metadata.items():
281
- self.assertEqual(post[k], v)
282
-
283
- # dumps and then loads to ensure round trip conversions.
284
- posttext = frontmatter.dumps(post, handler=self.handler)
285
- post_2 = frontmatter.loads(posttext)
286
-
287
- for k in post.metadata:
288
- self.assertEqual(post.metadata[k], post_2.metadata[k])
289
-
290
- self.assertEqual(post.content, post_2.content)
291
-
292
- def test_detect(self):
293
- text = self.read_from_tests()
294
-
295
- self.assertTrue(self.handler.detect(text))
296
-
297
- def test_split_content(self):
298
- text = self.read_from_tests()
299
-
300
- fm, content = self.handler.split(text)
301
-
302
- self.assertEqual(content, self.data["content"])
303
-
304
- def test_split_load(self):
305
- text = self.read_from_tests()
306
- fm, content = self.handler.split(text)
307
- fm_load = self.handler.load(fm)
308
-
309
- # The format of the failmsg makes it easy to copy into the test.
310
- any_fail = False
311
- failmsg = "The following metadata did not match the test:"
312
- for k in self.data["metadata"]:
313
- if fm_load[k] == self.data["metadata"][k]:
314
- continue
315
- any_fail = True
316
- failmsg += '\n"{0}": {1},'.format(k, repr(fm_load[k]))
317
-
318
- if any_fail:
319
- self.fail(failmsg)
320
-
321
-
322
- class YAMLHandlerTest(HandlerBaseTest, unittest.TestCase):
323
- def setUp(self):
324
- self.handler = YAMLHandler()
325
- self.data = {
326
- "filename": "tests/yaml/hello-markdown.md",
327
- # TODO: YAMLHandler.split() is prepending '\n' to the content
328
- "content": """\
329
-
330
- Title
331
- =====
332
-
333
- title2
334
- ------
335
-
336
- Hello.
337
-
338
- Just need three dashes
339
- ---
340
-
341
- And this shouldn't break.""",
342
- "metadata": {"test": "tester", "author": "bob", "something": "else"},
343
- }
344
-
345
-
346
- class JSONHandlerTest(HandlerBaseTest, unittest.TestCase):
347
- def setUp(self):
348
- self.handler = JSONHandler()
349
- self.data = {
350
- "filename": "tests/json/hello-json.md",
351
- # TODO: JSONHandler.split() is prepending '\n' to the content
352
- "content": """\
353
-
354
-
355
- Title
356
- =====
357
-
358
- title2
359
- ------
360
-
361
- Hello.
362
-
363
- Just need three dashes
364
- ---
365
-
366
- And this might break.
367
- """,
368
- "metadata": {"test": "tester", "author": "bob", "something": "else"},
369
- }
370
-
371
-
372
- class TOMLHandlerTest(HandlerBaseTest, unittest.TestCase):
373
- def setUp(self):
374
- self.handler = TOMLHandler()
375
- self.data = {
376
- "filename": "tests/toml/hello-toml.md",
377
- # TODO: TOMLHandler.split() is prepending '\n' to the content
378
- "content": """\
379
-
380
- Title
381
- =====
382
-
383
- title2
384
- ------
385
-
386
- Hello.
387
-
388
- Just need three dashes
389
- ---
390
-
391
- And this shouldn't break.
392
- """,
393
- "metadata": {"test": "tester", "author": "bob", "something": "else"},
394
- }
395
-
396
-
397
- if __name__ == "__main__":
398
- unittest.main()
@@ -1,5 +0,0 @@
1
- {
2
- "title": "Let's try unicode",
3
- "language": "\u4e2d\u6587",
4
- "content": "\u6b22\u8fce\u6765\u5230\u5927\u8fde\u6c34\u4ea7\u5b66\u9662\uff01"
5
- }
@@ -1,6 +0,0 @@
1
- ---
2
- title: "Let's try unicode"
3
- language: 中文
4
- ---
5
-
6
- 欢迎来到大连水产学院!
@@ -1,5 +0,0 @@
1
- {
2
- "test": "bob",
3
- "else": "kate",
4
- "content": "Here's some content."
5
- }
@@ -1,6 +0,0 @@
1
- ----
2
- test: bob
3
- else: kate
4
- ----
5
-
6
- Here's some content.
@@ -1,5 +0,0 @@
1
- {
2
- "test": "tester",
3
- "something": "else",
4
- "content": "This file has an extra space on the opening line of the frontmatter."
5
- }
@@ -1,6 +0,0 @@
1
- ---
2
- test: tester
3
- something: else
4
- ---
5
-
6
- This file has an extra space on the opening line of the frontmatter.
@@ -1,18 +0,0 @@
1
- ---
2
- test: tester
3
- author: bob
4
- something: else
5
- ---
6
-
7
- Title
8
- =====
9
-
10
- title2
11
- ------
12
-
13
- Hello.
14
-
15
- Just need three dashes
16
- ---
17
-
18
- And this shouldn't break.
@@ -1,6 +0,0 @@
1
- {
2
- "test": "tester",
3
- "author": "bob",
4
- "something": "else",
5
- "content": "Title\n=====\n\ntitle2\n------\n\nHello.\n\nJust need three dashes\n---\n\nAnd this shouldn't break."
6
- }
@@ -1,5 +0,0 @@
1
- {
2
- "title": "Hello, world!",
3
- "layout": "post",
4
- "content": "Well, hello there, world."
5
- }
@@ -1,6 +0,0 @@
1
- ---
2
- title: Hello, world!
3
- layout: post
4
- ---
5
-
6
- Well, hello there, world.
@@ -1,12 +0,0 @@
1
- ---
2
- title: "TODO: Understand Network Diagrams"
3
- layout: post
4
- published: true
5
- tags: [todo]
6
- ---
7
-
8
- Kim Rees, sitting in for Nathan Yau at [Flowing Data](http://flowingdata.com), has been posting examples of [network diagrams](http://flowingdata.com/category/visualization/network-visualization/) lately. I have to confess I'm stumped by most of them them. Or maybe I'm just overwhelmed. Maybe I'm [not alone](http://flowingdata.com/2012/05/28/network-diagrams-simplified/):
9
-
10
- > Network diagrams are notoriously messy. Even a small number of nodes can be overwhelmed by their chaotic placement and relationships. [Cody Dunne](http://www.cs.umd.edu/~cdunne/) of [HCIL](http://www.cs.umd.edu/hcil/) showed off [his new work in simplifying these complex structures](http://www.cs.umd.edu/localphp/hcil/tech-reports-search.php?number=2012-11). In essence, he aggregates leaf nodes into a fan glyph that describes the underlying data in its size, arc, and color. Span nodes are similarly captured into crescent glyphs. The result is an easy to read, high level look at the network. You can easily compare different sections of the network, understand areas that may have been occluded by the lines in a traditional diagram, and see relationships far more quickly.
11
-
12
- This seems like the kind of thing that could be useful for news, where we're often trying to understand and illustrate complex relationships. I'll have to find a good dataset to play with.
@@ -1,9 +0,0 @@
1
- {
2
- "title": "TODO: Understand Network Diagrams",
3
- "layout": "post",
4
- "published": true,
5
- "tags": [
6
- "todo"
7
- ],
8
- "content": "Kim Rees, sitting in for Nathan Yau at [Flowing Data](http://flowingdata.com), has been posting examples of [network diagrams](http://flowingdata.com/category/visualization/network-visualization/) lately. I have to confess I'm stumped by most of them them. Or maybe I'm just overwhelmed. Maybe I'm [not alone](http://flowingdata.com/2012/05/28/network-diagrams-simplified/):\n\n> Network diagrams are notoriously messy. Even a small number of nodes can be overwhelmed by their chaotic placement and relationships. [Cody Dunne](http://www.cs.umd.edu/~cdunne/) of [HCIL](http://www.cs.umd.edu/hcil/) showed off [his new work in simplifying these complex structures](http://www.cs.umd.edu/localphp/hcil/tech-reports-search.php?number=2012-11). In essence, he aggregates leaf nodes into a fan glyph that describes the underlying data in its size, arc, and color. Span nodes are similarly captured into crescent glyphs. The result is an easy to read, high level look at the network. You can easily compare different sections of the network, understand areas that may have been occluded by the lines in a traditional diagram, and see relationships far more quickly.\n\nThis seems like the kind of thing that could be useful for news, where we're often trying to understand and illustrate complex relationships. I'll have to find a good dataset to play with."
9
- }
@@ -1,21 +0,0 @@
1
- ---
2
- destination:
3
- encoding:
4
- xz:
5
- enabled: yes
6
- min_size: 5120
7
- options:
8
- path_filter:
9
- result:
10
- append_to_file:
11
- append_to_lafs_dir:
12
- print_to_stdout: yes
13
- url: http://localhost:3456/uri
14
- filter:
15
- - Длинный стринг на русском
16
- - Еще одна длинная строка
17
- ---
18
-
19
- This is a test of both unicode and prettier dumping. The above metadata comes from the [pretty-yaml](https://github.com/mk-fg/pretty-yaml) readme file.
20
-
21
- Metadata should be dumped in order.
@@ -1,23 +0,0 @@
1
- {
2
- "destination": {
3
- "encoding": {
4
- "xz": {
5
- "enabled": true,
6
- "min_size": 5120,
7
- "options": null,
8
- "path_filter": null
9
- }
10
- },
11
- "result": {
12
- "append_to_file": null,
13
- "append_to_lafs_dir": null,
14
- "print_to_stdout": true
15
- },
16
- "url": "http://localhost:3456/uri"
17
- },
18
- "filter": [
19
- "\u0414\u043b\u0438\u043d\u043d\u044b\u0439 \u0441\u0442\u0440\u0438\u043d\u0433 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c",
20
- "\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u0434\u043b\u0438\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430"
21
- ],
22
- "content": "This is a test of both unicode and prettier dumping. The above metadata comes from the [pretty-yaml](https://github.com/mk-fg/pretty-yaml) readme file.\n\nMetadata should be dumped in order."
23
- }