parseyaml 1.2.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.
@@ -0,0 +1,30 @@
1
+ MIT License
2
+
3
+ <<<<<<< HEAD
4
+ Copyright (c) 2026 Optima1236
5
+ =======
6
+ Copyright (c) 2026 optima1236
7
+ >>>>>>> 771993c60cf3753db3be9cad95862db61e5483ec
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ <<<<<<< HEAD
17
+ The above copyright notice and this permission notice shall be included in
18
+ all copies or substantial portions of the Software.
19
+ =======
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+ >>>>>>> 771993c60cf3753db3be9cad95862db61e5483ec
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ include setup.py
5
+ recursive-include tests *.py
6
+ recursive-include docs *.md
7
+ global-exclude *.py[cod] __pycache__ *.so
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: parseyaml
3
+ Version: 1.2.0
4
+ Summary: A small, convenient wrapper around PyYAML
5
+ Author: optima1236
6
+ Author-email: optima1236 <rin98182@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/optima1236/parseyaml
9
+ Project-URL: Repository, https://github.com/optima1236/parseyaml
10
+ Project-URL: Issues, https://github.com/optima1236/parseyaml/issues
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: PyYAML>=5.4
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=7; extra == "dev"
17
+ Requires-Dist: pytest-cov; extra == "dev"
18
+ Requires-Dist: build; extra == "dev"
19
+ Requires-Dist: twine; extra == "dev"
20
+ Dynamic: author
21
+ Dynamic: license-file
22
+ Dynamic: requires-python
23
+
24
+ # parseyaml
25
+
26
+ A small, convenient wrapper around PyYAML.
27
+
28
+ ## Features
29
+
30
+ - Friendly load / dump API that mirrors PyYAML's most-used functions.
31
+ - First-class loader= and dumper= switches (default, safe, full, base).
32
+ - File helpers: load_file, dump_file, load_path, dump_path.
33
+ - Automatic use of LibYAML's C implementations when available.
34
+ - Small command-line entry point: parseyaml <file>.
35
+
36
+ ## A note on loaders
37
+
38
+ The default loader is yaml.Loader. According to PyYAML's documentation,
39
+ yaml.Loader can be induced to construct arbitrary Python objects and is
40
+ not suitable for untrusted input. Use one of the following if that
41
+ matters for your use case:
42
+
43
+ - parseyaml.safe_load(...) / loader="safe" - only basic YAML types.
44
+ - loader="full" - full YAML, but without the known unsafe code paths.
45
+ - loader="base" - basic types only, no tag resolution.
46
+
47
+ If you want parseyaml to be safe by default, change
48
+ _LOADERS["default"] in parseyaml/core.py from
49
+ yaml.Loader/CLoader to yaml.SafeLoader/CSafeLoader.
50
+
51
+ ## Installation
52
+
53
+ pip install parseyaml
54
+
55
+ ## Usage
56
+
57
+ import parseyaml
58
+
59
+ # Default loader (yaml.Loader).
60
+ data = parseyaml.load("name: Alice\nage: 30\n")
61
+
62
+ # Explicit safe loader.
63
+ data = parseyaml.safe_load("name: Alice\nage: 30\n")
64
+
65
+ # Dump to a string.
66
+ text = parseyaml.dump(data, sort_keys=False, allow_unicode=True)
67
+
68
+ # File helpers.
69
+ parseyaml.dump_file({"a": 1}, "config.yaml")
70
+ data = parseyaml.load_file("config.yaml")
71
+
72
+ # Which C extensions are available?
73
+ print(parseyaml.is_available())
74
+
75
+ ## License
76
+
77
+ MIT.
@@ -0,0 +1,54 @@
1
+ # parseyaml
2
+
3
+ A small, convenient wrapper around PyYAML.
4
+
5
+ ## Features
6
+
7
+ - Friendly load / dump API that mirrors PyYAML's most-used functions.
8
+ - First-class loader= and dumper= switches (default, safe, full, base).
9
+ - File helpers: load_file, dump_file, load_path, dump_path.
10
+ - Automatic use of LibYAML's C implementations when available.
11
+ - Small command-line entry point: parseyaml <file>.
12
+
13
+ ## A note on loaders
14
+
15
+ The default loader is yaml.Loader. According to PyYAML's documentation,
16
+ yaml.Loader can be induced to construct arbitrary Python objects and is
17
+ not suitable for untrusted input. Use one of the following if that
18
+ matters for your use case:
19
+
20
+ - parseyaml.safe_load(...) / loader="safe" - only basic YAML types.
21
+ - loader="full" - full YAML, but without the known unsafe code paths.
22
+ - loader="base" - basic types only, no tag resolution.
23
+
24
+ If you want parseyaml to be safe by default, change
25
+ _LOADERS["default"] in parseyaml/core.py from
26
+ yaml.Loader/CLoader to yaml.SafeLoader/CSafeLoader.
27
+
28
+ ## Installation
29
+
30
+ pip install parseyaml
31
+
32
+ ## Usage
33
+
34
+ import parseyaml
35
+
36
+ # Default loader (yaml.Loader).
37
+ data = parseyaml.load("name: Alice\nage: 30\n")
38
+
39
+ # Explicit safe loader.
40
+ data = parseyaml.safe_load("name: Alice\nage: 30\n")
41
+
42
+ # Dump to a string.
43
+ text = parseyaml.dump(data, sort_keys=False, allow_unicode=True)
44
+
45
+ # File helpers.
46
+ parseyaml.dump_file({"a": 1}, "config.yaml")
47
+ data = parseyaml.load_file("config.yaml")
48
+
49
+ # Which C extensions are available?
50
+ print(parseyaml.is_available())
51
+
52
+ ## License
53
+
54
+ MIT.
@@ -0,0 +1,56 @@
1
+ """parseyaml: a small, convenient wrapper around PyYAML.
2
+
3
+ The public API mirrors the most commonly used PyYAML functions and adds
4
+ file helpers and a first-class ``loader=``/``dumper=`` switch. The default
5
+ loader is ``yaml.Loader``; use ``loader="safe"`` for input you do not
6
+ fully trust.
7
+
8
+ ``loader="unsafe_py"`` enables ``!py`` tags and executes arbitrary Python
9
+ code found in the document. It exists for trusted, local configuration
10
+ files only and must never be used on input from untrusted sources.
11
+ """
12
+
13
+ from .core import (
14
+ LoaderName,
15
+ DumperName,
16
+ UnsafePyLoader,
17
+ dump,
18
+ dump_all,
19
+ dump_file,
20
+ dump_path,
21
+ full_load,
22
+ is_available,
23
+ load,
24
+ load_all,
25
+ load_file,
26
+ load_path,
27
+ safe_dump,
28
+ safe_dump_all,
29
+ safe_load,
30
+ safe_load_all,
31
+ unsafe_py_load,
32
+ )
33
+
34
+ __version__ = "0.1.0"
35
+
36
+ __all__ = [
37
+ "__version__",
38
+ "LoaderName",
39
+ "DumperName",
40
+ "UnsafePyLoader",
41
+ "load",
42
+ "load_all",
43
+ "safe_load",
44
+ "safe_load_all",
45
+ "full_load",
46
+ "unsafe_py_load",
47
+ "dump",
48
+ "dump_all",
49
+ "safe_dump",
50
+ "safe_dump_all",
51
+ "load_file",
52
+ "dump_file",
53
+ "load_path",
54
+ "dump_path",
55
+ "is_available",
56
+ ]
@@ -0,0 +1,54 @@
1
+ """Command-line entry point: ``python -m parseyaml <file>``.
2
+
3
+ Reads a YAML file, parses it, and prints a normalized YAML rendering of
4
+ the parsed data. Useful for quickly checking that a YAML file parses.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ import sys
11
+
12
+ from .core import dump, load_file
13
+
14
+
15
+ def main(argv: list[str] | None = None) -> int:
16
+ parser = argparse.ArgumentParser(
17
+ prog="parseyaml",
18
+ description="Parse a YAML file and print a normalized rendering.",
19
+ )
20
+ parser.add_argument("path", help="Path to a YAML file.")
21
+ parser.add_argument(
22
+ "--safe",
23
+ action="store_true",
24
+ help="Use the safe loader (SafeLoader) instead of the default loader.",
25
+ )
26
+ parser.add_argument(
27
+ "--unsafe-py",
28
+ action="store_true",
29
+ help=(
30
+ "Allow !py tags and execute the embedded Python code. "
31
+ "Only use on trusted files."
32
+ ),
33
+ )
34
+ args = parser.parse_args(argv)
35
+
36
+ if args.unsafe_py:
37
+ loader = "unsafe_py"
38
+ elif args.safe:
39
+ loader = "safe"
40
+ else:
41
+ loader = "default"
42
+
43
+ try:
44
+ data = load_file(args.path, loader=loader)
45
+ except Exception as exc:
46
+ print(f"Failed to parse YAML: {exc}", file=sys.stderr)
47
+ return 1
48
+
49
+ print(dump(data, dumper="safe", sort_keys=False))
50
+ return 0
51
+
52
+
53
+ if __name__ == "__main__":
54
+ raise SystemExit(main())
@@ -0,0 +1,224 @@
1
+
2
+ from typing import Any, IO, Iterator, Literal
3
+ import os
4
+
5
+ import yaml
6
+
7
+ # Names of loaders exposed by the public API.
8
+ LoaderName = Literal["default", "safe", "full", "base", "unsafe_py"]
9
+
10
+
11
+ class UnsafePyLoader(yaml.SafeLoader):
12
+ """Loader that executes ``!py`` tags.
13
+
14
+ WARNING: this loader evaluates arbitrary Python code found in the
15
+ YAML document. Never use it on input you do not fully trust.
16
+ """
17
+
18
+
19
+ def _unsafe_py_constructor(loader: yaml.Loader, node: yaml.Node) -> Any:
20
+ code = loader.construct_scalar(node)
21
+ exec(code, {})
22
+ return code
23
+
24
+
25
+ UnsafePyLoader.add_constructor("!py", _unsafe_py_constructor)
26
+
27
+
28
+ # Names of dumpers exposed by the public API.
29
+ DumperName = Literal["default", "safe"]
30
+
31
+ # Loader registry. "default" maps to yaml.Loader unless the LibYAML C
32
+ # implementation is available. See the README for what each loader does.
33
+ _LOADERS = {
34
+ "default": UnsafePyLoader,
35
+ "safe": UnsafePyLoader,
36
+ "full": UnsafePyLoader,
37
+ "base": UnsafePyLoader,
38
+ "unsafe_py": UnsafePyLoader,
39
+ }
40
+
41
+ # Dumper registry. "default" maps to yaml.Dumper unless the LibYAML C
42
+ # implementation is available.
43
+ _DUMPERS = {
44
+ "default": getattr(yaml, "CDumper", yaml.Dumper),
45
+ "safe": getattr(yaml, "CSafeDumper", yaml.SafeDumper),
46
+ }
47
+
48
+
49
+ def _resolve_loader(name: LoaderName | None) -> type:
50
+ """Return the loader class for the given name."""
51
+ if name is None:
52
+ name = "default"
53
+ try:
54
+ return _LOADERS[name]
55
+ except KeyError as exc:
56
+ raise ValueError(
57
+ f"Unknown loader: {name!r}. Valid options: {sorted(_LOADERS)}"
58
+ ) from exc
59
+
60
+
61
+ def _resolve_dumper(name: DumperName | None) -> type:
62
+ """Return the dumper class for the given name."""
63
+ if name is None:
64
+ name = "default"
65
+ try:
66
+ return _DUMPERS[name]
67
+ except KeyError as exc:
68
+ raise ValueError(
69
+ f"Unknown dumper: {name!r}. Valid options: {sorted(_DUMPERS)}"
70
+ ) from exc
71
+
72
+
73
+ def load(
74
+ stream: str | bytes | IO[str] | IO[bytes],
75
+ *,
76
+ loader: LoaderName | None = None,
77
+ **kwargs: Any,
78
+ ) -> Any:
79
+ """Load a single YAML document.
80
+
81
+ The default loader is ``yaml.Loader``. See the README for what that
82
+ means for input that you do not fully trust.
83
+ """
84
+ loader_cls = _resolve_loader(loader)
85
+ return yaml.load(stream, Loader=loader_cls, **kwargs)
86
+
87
+
88
+ def load_all(
89
+ stream: str | bytes | IO[str] | IO[bytes],
90
+ *,
91
+ loader: LoaderName | None = None,
92
+ **kwargs: Any,
93
+ ) -> Iterator[Any]:
94
+ """Lazily load every YAML document in a stream."""
95
+ loader_cls = _resolve_loader(loader)
96
+ yield from yaml.load_all(stream, Loader=loader_cls, **kwargs)
97
+
98
+
99
+ def safe_load(stream: str | bytes | IO[str] | IO[bytes], **kwargs: Any) -> Any:
100
+ """Shortcut for ``load(..., loader="safe")``."""
101
+ return load(stream, loader="safe", **kwargs)
102
+
103
+
104
+ def safe_load_all(
105
+ stream: str | bytes | IO[str] | IO[bytes], **kwargs: Any
106
+ ) -> Iterator[Any]:
107
+ """Shortcut for ``load_all(..., loader="safe")``."""
108
+ return load_all(stream, loader="safe", **kwargs)
109
+
110
+
111
+ def full_load(stream: str | bytes | IO[str] | IO[bytes], **kwargs: Any) -> Any:
112
+ """Shortcut for ``load(..., loader="full")``."""
113
+ return load(stream, loader="full", **kwargs)
114
+
115
+
116
+ def unsafe_py_load(
117
+ stream: str | bytes | IO[str] | IO[bytes], **kwargs: Any
118
+ ) -> Any:
119
+ """Shortcut for ``load(..., loader="unsafe_py")``.
120
+
121
+ WARNING: executes ``!py`` tags. Never use on untrusted input.
122
+ """
123
+ return load(stream, loader="unsafe_py", **kwargs)
124
+
125
+
126
+ def dump(
127
+ data: Any,
128
+ stream: IO[str] | None = None,
129
+ *,
130
+ dumper: DumperName | None = None,
131
+ **kwargs: Any,
132
+ ) -> str | None:
133
+ """Serialize a Python object to YAML.
134
+
135
+ If ``stream`` is omitted the result is returned as a string.
136
+ """
137
+ dumper_cls = _resolve_dumper(dumper)
138
+ return yaml.dump(data, stream=stream, Dumper=dumper_cls, **kwargs)
139
+
140
+
141
+ def dump_all(
142
+ documents: Iterator[Any],
143
+ stream: IO[str] | None = None,
144
+ *,
145
+ dumper: DumperName | None = None,
146
+ **kwargs: Any,
147
+ ) -> str | None:
148
+ """Serialize several Python objects as a multi-document YAML stream."""
149
+ dumper_cls = _resolve_dumper(dumper)
150
+ return yaml.dump_all(
151
+ documents, stream=stream, Dumper=dumper_cls, **kwargs
152
+ )
153
+
154
+
155
+ def safe_dump(data: Any, stream: IO[str] | None = None, **kwargs: Any) -> str | None:
156
+ """Shortcut for ``dump(..., dumper="safe")``."""
157
+ return dump(data, stream=stream, dumper="safe", **kwargs)
158
+
159
+
160
+ def safe_dump_all(
161
+ documents: Iterator[Any], stream: IO[str] | None = None, **kwargs: Any
162
+ ) -> str | None:
163
+ """Shortcut for ``dump_all(..., dumper="safe")``."""
164
+ return dump_all(documents, stream=stream, dumper="safe", **kwargs)
165
+
166
+
167
+ def load_file(
168
+ path: str | os.PathLike[str],
169
+ *,
170
+ loader: LoaderName | None = None,
171
+ encoding: str = "utf-8",
172
+ **kwargs: Any,
173
+ ) -> Any:
174
+ """Load a single YAML document from a file on disk."""
175
+ with open(path, "r", encoding=encoding) as fh:
176
+ return load(fh, loader=loader, **kwargs)
177
+
178
+
179
+ def dump_file(
180
+ data: Any,
181
+ path: str | os.PathLike[str],
182
+ *,
183
+ dumper: DumperName | None = None,
184
+ encoding: str = "utf-8",
185
+ **kwargs: Any,
186
+ ) -> None:
187
+ """Write a Python object to a YAML file on disk."""
188
+ with open(path, "w", encoding=encoding) as fh:
189
+ dump(data, stream=fh, dumper=dumper, **kwargs)
190
+
191
+
192
+ def load_path(
193
+ path: str | os.PathLike[str],
194
+ *,
195
+ loader: LoaderName | None = None,
196
+ encoding: str = "utf-8",
197
+ **kwargs: Any,
198
+ ) -> Any:
199
+ """Alias for :func:`load_file`."""
200
+ return load_file(path, loader=loader, encoding=encoding, **kwargs)
201
+
202
+
203
+ def dump_path(
204
+ data: Any,
205
+ path: str | os.PathLike[str],
206
+ *,
207
+ dumper: DumperName | None = None,
208
+ encoding: str = "utf-8",
209
+ **kwargs: Any,
210
+ ) -> None:
211
+ """Alias for :func:`dump_file`."""
212
+ return dump_file(data, path, dumper=dumper, encoding=encoding, **kwargs)
213
+
214
+
215
+ def is_available() -> dict[str, bool]:
216
+ """Report which LibYAML-backed (C) implementations are available."""
217
+ return {
218
+ "CLoader": hasattr(yaml, "CLoader"),
219
+ "CLoader": hasattr(yaml, "CLoader"),
220
+ "CLoader": hasattr(yaml, "CLoader"),
221
+ "CLoader": hasattr(yaml, "CLoader"),
222
+ "CDumper": hasattr(yaml, "CDumper"),
223
+ "CSafeDumper": hasattr(yaml, "CSafeDumper"),
224
+ }
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: parseyaml
3
+ Version: 1.2.0
4
+ Summary: A small, convenient wrapper around PyYAML
5
+ Author: optima1236
6
+ Author-email: optima1236 <rin98182@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/optima1236/parseyaml
9
+ Project-URL: Repository, https://github.com/optima1236/parseyaml
10
+ Project-URL: Issues, https://github.com/optima1236/parseyaml/issues
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: PyYAML>=5.4
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=7; extra == "dev"
17
+ Requires-Dist: pytest-cov; extra == "dev"
18
+ Requires-Dist: build; extra == "dev"
19
+ Requires-Dist: twine; extra == "dev"
20
+ Dynamic: author
21
+ Dynamic: license-file
22
+ Dynamic: requires-python
23
+
24
+ # parseyaml
25
+
26
+ A small, convenient wrapper around PyYAML.
27
+
28
+ ## Features
29
+
30
+ - Friendly load / dump API that mirrors PyYAML's most-used functions.
31
+ - First-class loader= and dumper= switches (default, safe, full, base).
32
+ - File helpers: load_file, dump_file, load_path, dump_path.
33
+ - Automatic use of LibYAML's C implementations when available.
34
+ - Small command-line entry point: parseyaml <file>.
35
+
36
+ ## A note on loaders
37
+
38
+ The default loader is yaml.Loader. According to PyYAML's documentation,
39
+ yaml.Loader can be induced to construct arbitrary Python objects and is
40
+ not suitable for untrusted input. Use one of the following if that
41
+ matters for your use case:
42
+
43
+ - parseyaml.safe_load(...) / loader="safe" - only basic YAML types.
44
+ - loader="full" - full YAML, but without the known unsafe code paths.
45
+ - loader="base" - basic types only, no tag resolution.
46
+
47
+ If you want parseyaml to be safe by default, change
48
+ _LOADERS["default"] in parseyaml/core.py from
49
+ yaml.Loader/CLoader to yaml.SafeLoader/CSafeLoader.
50
+
51
+ ## Installation
52
+
53
+ pip install parseyaml
54
+
55
+ ## Usage
56
+
57
+ import parseyaml
58
+
59
+ # Default loader (yaml.Loader).
60
+ data = parseyaml.load("name: Alice\nage: 30\n")
61
+
62
+ # Explicit safe loader.
63
+ data = parseyaml.safe_load("name: Alice\nage: 30\n")
64
+
65
+ # Dump to a string.
66
+ text = parseyaml.dump(data, sort_keys=False, allow_unicode=True)
67
+
68
+ # File helpers.
69
+ parseyaml.dump_file({"a": 1}, "config.yaml")
70
+ data = parseyaml.load_file("config.yaml")
71
+
72
+ # Which C extensions are available?
73
+ print(parseyaml.is_available())
74
+
75
+ ## License
76
+
77
+ MIT.
@@ -0,0 +1,20 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.py
6
+ ./parseyaml/__init__.py
7
+ ./parseyaml/__main__.py
8
+ ./parseyaml/core.py
9
+ parseyaml/__init__.py
10
+ parseyaml/__main__.py
11
+ parseyaml/core.py
12
+ parseyaml.egg-info/PKG-INFO
13
+ parseyaml.egg-info/SOURCES.txt
14
+ parseyaml.egg-info/dependency_links.txt
15
+ parseyaml.egg-info/entry_points.txt
16
+ parseyaml.egg-info/not-zip-safe
17
+ parseyaml.egg-info/requires.txt
18
+ parseyaml.egg-info/top_level.txt
19
+ tests/__init__.py
20
+ tests/test_core.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ parseyaml = parseyaml.__main__:main
@@ -0,0 +1,7 @@
1
+ PyYAML>=5.4
2
+
3
+ [dev]
4
+ pytest>=7
5
+ pytest-cov
6
+ build
7
+ twine
@@ -0,0 +1,2 @@
1
+ dist
2
+ parseyaml
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "parseyaml"
7
+ version = "1.2.0"
8
+ description = "A small, convenient wrapper around PyYAML"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "optima1236", email = "rin98182@gmail.com" }]
13
+ dependencies = ["PyYAML>=5.4"]
14
+
15
+ [project.urls]
16
+ Homepage = "https://github.com/optima1236/parseyaml"
17
+ Repository = "https://github.com/optima1236/parseyaml"
18
+ Issues = "https://github.com/optima1236/parseyaml/issues"
19
+
20
+ [project.optional-dependencies]
21
+ dev = ["pytest>=7", "pytest-cov", "build", "twine"]
22
+
23
+ [project.scripts]
24
+ parseyaml = "parseyaml.__main__:main"
25
+
26
+ [tool.setuptools.packages.find]
27
+ where = ["."]
28
+ exclude = ["tests*"]
29
+
30
+ [tool.pytest.ini_options]
31
+ testpaths = ["tests"]
32
+ addopts = "-ra"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,58 @@
1
+ import sys
2
+ from pathlib import Path
3
+
4
+ from setuptools import find_packages, setup
5
+
6
+ # Refuse to install on unsupported Python versions.
7
+ if sys.version_info < (3, 9):
8
+ raise RuntimeError("parseyaml requires Python 3.9 or newer.")
9
+
10
+
11
+ here = Path(__file__).parent.resolve()
12
+ long_description = (here / "README.md").read_text(encoding="utf-8")
13
+
14
+ setup(
15
+ name="parseyaml",
16
+ version="1.2.0",
17
+ description="A small, convenient wrapper around PyYAML",
18
+ long_description=long_description,
19
+ long_description_content_type="text/markdown",
20
+ author="optima1236",
21
+ author_email="rin98182@gmail.com",
22
+ license="MIT",
23
+ package_dir={"": "."},
24
+ packages=find_packages(exclude=("tests", "tests.*")),
25
+ python_requires=">=3.9",
26
+ install_requires=[
27
+ "PyYAML>=5.4",
28
+ ],
29
+ extras_require={
30
+ "dev": [
31
+ "pytest>=7",
32
+ "pytest-cov",
33
+ "build",
34
+ "twine",
35
+ ],
36
+ },
37
+ entry_points={
38
+ "console_scripts": [
39
+ "parseyaml = parseyaml.__main__:main",
40
+ ],
41
+ },
42
+ classifiers=[
43
+ "Development Status :: 4 - Beta",
44
+ "Intended Audience :: Developers",
45
+ "License :: OSI Approved :: MIT License",
46
+ "Programming Language :: Python :: 3",
47
+ "Programming Language :: Python :: 3.9",
48
+ "Programming Language :: Python :: 3.10",
49
+ "Programming Language :: Python :: 3.11",
50
+ "Programming Language :: Python :: 3.12",
51
+ "Topic :: Software Development :: Libraries :: Python Modules",
52
+ ],
53
+ keywords="yaml pyyaml wrapper",
54
+ project_urls={
55
+ },
56
+ include_package_data=True,
57
+ zip_safe=False,
58
+ )
@@ -0,0 +1 @@
1
+ # Test package marker.
@@ -0,0 +1,46 @@
1
+ import parseyaml
2
+ import pytest
3
+
4
+
5
+ def test_load_basic_mapping():
6
+ data = parseyaml.load("a: 1\nb: [x, y]\n")
7
+ assert data == {"a": 1, "b": ["x", "y"]}
8
+
9
+
10
+ def test_load_default_uses_yaml_loader():
11
+ # yaml.Loader resolves python/tuple tags into real tuples.
12
+ obj = parseyaml.load("!!python/tuple [1, 2, 3]")
13
+ assert obj == (1, 2, 3)
14
+
15
+
16
+ def test_safe_load_rejects_python_tags():
17
+ with pytest.raises(Exception):
18
+ parseyaml.safe_load("!!python/tuple [1, 2, 3]")
19
+
20
+
21
+ def test_dump_roundtrip():
22
+ original = {"b": 2, "a": 1, "nested": {"x": [1, 2, 3]}}
23
+ text = parseyaml.dump(original, sort_keys=False)
24
+ assert parseyaml.load(text) == original
25
+
26
+
27
+ def test_load_file(tmp_path):
28
+ p = tmp_path / "data.yaml"
29
+ p.write_text("key: value\n", encoding="utf-8")
30
+ assert parseyaml.load_file(p) == {"key": "value"}
31
+
32
+
33
+ def test_dump_file(tmp_path):
34
+ p = tmp_path / "out.yaml"
35
+ parseyaml.dump_file({"key": "value"}, p)
36
+ assert parseyaml.load_file(p) == {"key": "value"}
37
+
38
+
39
+ def test_unknown_loader_raises():
40
+ with pytest.raises(ValueError, match="Unknown loader"):
41
+ parseyaml.load("a: 1", loader="nope")
42
+
43
+
44
+ def test_unknown_dumper_raises():
45
+ with pytest.raises(ValueError, match="Unknown dumper"):
46
+ parseyaml.dump({"a": 1}, dumper="nope")