cayaml 0.1.0.dev2__py3-none-any.whl

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.
cayaml/__init__.py ADDED
@@ -0,0 +1,168 @@
1
+ """
2
+ Minimal YAML Parser and Unparser
3
+
4
+ This module provides a very basic YAML parser and unparser that supports a subset
5
+ of YAML syntax (mappings and sequences, with simple scalars). It uses only Python's
6
+ built-in libraries and is intended for simple use cases.
7
+
8
+ Usage:
9
+ data = parse_yaml(yaml_string)
10
+ yaml_string = unparse_yaml(data)
11
+ """
12
+
13
+
14
+ def get_indent(line):
15
+ """Return the number of leading spaces in a line."""
16
+ return len(line) - len(line.lstrip(" "))
17
+
18
+
19
+ def parse_scalar(value):
20
+ """Convert a scalar string into int, float, bool, None or leave as string."""
21
+ # Remove quotes if present
22
+ if (value.startswith('"') and value.endswith('"')) or (
23
+ value.startswith("'") and value.endswith("'")
24
+ ):
25
+ return value[1:-1]
26
+ lower = value.lower()
27
+ if lower == "true":
28
+ return True
29
+ if lower == "false":
30
+ return False
31
+ if lower in ["null", "~"]:
32
+ return None
33
+ try:
34
+ return int(value)
35
+ except ValueError:
36
+ pass
37
+ try:
38
+ return float(value)
39
+ except ValueError:
40
+ pass
41
+ return value
42
+
43
+
44
+ def parse_mapping(lines, indent):
45
+ """Parse a block of lines representing a mapping."""
46
+ mapping = {}
47
+ while lines and get_indent(lines[0]) >= indent:
48
+ if get_indent(lines[0]) != indent:
49
+ break
50
+ line = lines.pop(0)
51
+ # Ignore comment lines
52
+ if line.strip().startswith("#"):
53
+ continue
54
+ if ":" not in line:
55
+ continue # Skip lines that do not look like key: value pairs
56
+ key, _, value = line.strip().partition(":")
57
+ key = key.strip()
58
+ value = value.strip()
59
+ if value == "":
60
+ # If no inline value, check if a nested block follows.
61
+ if lines and get_indent(lines[0]) > indent:
62
+ value, _ = parse_block(lines, get_indent(lines[0]))
63
+ else:
64
+ value = None
65
+ else:
66
+ value = parse_scalar(value)
67
+ mapping[key] = value
68
+ return mapping
69
+
70
+
71
+ def parse_list(lines, indent):
72
+ """Parse a block of lines representing a list."""
73
+ lst = []
74
+ while (
75
+ lines and get_indent(lines[0]) == indent and lines[0].lstrip().startswith("-")
76
+ ):
77
+ line = lines.pop(0)
78
+ # Remove the dash marker and get the content.
79
+ content = line.lstrip()[1:].strip()
80
+ if content == "":
81
+ # If nothing follows the dash, check for an indented block.
82
+ if lines and get_indent(lines[0]) > indent:
83
+ item, _ = parse_block(lines, get_indent(lines[0]))
84
+ else:
85
+ item = None
86
+ else:
87
+ item = parse_scalar(content)
88
+ # If the next line is indented more, treat it as a nested block.
89
+ if lines and get_indent(lines[0]) > indent:
90
+ extra, _ = parse_block(lines, get_indent(lines[0]))
91
+ # If the inline value is a mapping, merge the extra block.
92
+ if isinstance(item, dict) and isinstance(extra, dict):
93
+ item.update(extra)
94
+ else:
95
+ item = extra
96
+ lst.append(item)
97
+ return lst
98
+
99
+
100
+ def parse_block(lines, indent):
101
+ """Determine if the current block is a list or mapping and parse accordingly."""
102
+ if not lines:
103
+ return None, lines
104
+ # If the current line starts with a dash, treat as a list; otherwise, a mapping.
105
+ if lines[0].lstrip().startswith("-"):
106
+ result = parse_list(lines, indent)
107
+ else:
108
+ result = parse_mapping(lines, indent)
109
+ return result, lines
110
+
111
+
112
+ def parse_yaml(yaml_str):
113
+ """
114
+ Parse a YAML string and return the corresponding Python data structure.
115
+ Supports a minimal subset of YAML.
116
+ """
117
+ lines = yaml_str.splitlines()
118
+ # Remove completely blank lines.
119
+ lines = [line for line in lines if line.strip() != ""]
120
+ result, _ = parse_block(lines, 0)
121
+ return result
122
+
123
+
124
+ def format_scalar(value):
125
+ """Format a scalar value as a YAML string."""
126
+ if value is None:
127
+ return "null"
128
+ if isinstance(value, bool):
129
+ return "true" if value else "false"
130
+ if isinstance(value, (int, float)):
131
+ return str(value)
132
+ if isinstance(value, str):
133
+ # Quote the string if it contains spaces or special characters.
134
+ if not value or any(c in value for c in [" ", ":", "-", "#"]):
135
+ escaped = value.replace('"', '\\"')
136
+ return f'"{escaped}"'
137
+ return value
138
+ return str(value)
139
+
140
+
141
+ def unparse_yaml(data, indent=0):
142
+ """
143
+ Convert a Python data structure into a YAML-formatted string.
144
+ Supports a minimal subset of YAML.
145
+ """
146
+ lines = []
147
+ prefix = " " * indent
148
+ if isinstance(data, dict):
149
+ for key, value in data.items():
150
+ if isinstance(value, (dict, list)):
151
+ lines.append(f"{prefix}{key}:")
152
+ lines.append(unparse_yaml(value, indent + 2))
153
+ else:
154
+ lines.append(f"{prefix}{key}: {format_scalar(value)}")
155
+ elif isinstance(data, list):
156
+ for item in data:
157
+ if isinstance(item, (dict, list)):
158
+ lines.append(f"{prefix}-")
159
+ lines.append(unparse_yaml(item, indent + 2))
160
+ else:
161
+ lines.append(f"{prefix}- {format_scalar(item)}")
162
+ else:
163
+ lines.append(f"{prefix}{format_scalar(data)}")
164
+ return "\n".join(lines)
165
+
166
+
167
+ # Public API
168
+ __all__ = ["parse_yaml", "unparse_yaml"]
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.3
2
+ Name: cayaml
3
+ Version: 0.1.0.dev2
4
+ Summary: Swarmauri's Canon Yaml Handler
5
+ License: Apache-2.0
6
+ Author: Jacob Stewart
7
+ Author-email: jacob@swarmauri.com
8
+ Requires-Python: >=3.10,<3.13
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Description-Content-Type: text/markdown
14
+
15
+
@@ -0,0 +1,4 @@
1
+ cayaml/__init__.py,sha256=7T-rcRLCZTemVt0grS40pvaYg3OB-YjPyRiZibxp4C0,5421
2
+ cayaml-0.1.0.dev2.dist-info/METADATA,sha256=q3r1lmMc372TZ6GiqXehQt-fwgIMLoEbulza6yFv0Tg,459
3
+ cayaml-0.1.0.dev2.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
4
+ cayaml-0.1.0.dev2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.2
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any