diff options
-rw-r--r-- | __init__.py | 2 | ||||
-rw-r--r-- | _doc/detail.rst | 26 | ||||
-rw-r--r-- | _test/roundtrip.py | 21 | ||||
-rw-r--r-- | _test/test_indentation.py | 20 | ||||
-rw-r--r-- | dumper.py | 16 | ||||
-rw-r--r-- | emitter.py | 32 | ||||
-rw-r--r-- | main.py | 14 |
7 files changed, 102 insertions, 29 deletions
diff --git a/__init__.py b/__init__.py index 5e96205..10de7b0 100644 --- a/__init__.py +++ b/__init__.py @@ -9,7 +9,7 @@ from __future__ import absolute_import _package_data = dict( full_package_name="ruamel.yaml", - version_info=(0, 11, 8), + version_info=(0, 11, 9), author="Anthon van der Neut", author_email="a.van.der.neut@ruamel.eu", description="ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order", # NOQA diff --git a/_doc/detail.rst b/_doc/detail.rst index efcdac7..19142e2 100644 --- a/_doc/detail.rst +++ b/_doc/detail.rst @@ -27,7 +27,6 @@ Details - preservation of whitelines after block scalars. Contributed by Sam Thursfield. - Indentation of block sequences ------------------------------ @@ -68,6 +67,31 @@ If the ``block_seq_indent`` is only one less than the indent, there is not enough room to put the space that has to follow the dash. In that case the element is pushed to the next line. If you specify ``block_seq_indent>=indent``, then the emitter adjusts the ``indent`` value to equal ``block_seq_indent + 1``. + +Positioning ':' in top level mappings, prefix in ':' +---------------------------------------------------- + +If you want your toplevel mappings to look like:: + + library version: 1 + comment : | + this is just a first try + +then call ``round_trip_dump()`` with ``top_level_colon_align=True`` +(and ``indent=4``). ``True`` causes calculation based on the longest key, +but you can also explicitly set a number. + +If you want an extra space between a mapping key and the colon specify +``prefix_colon=' '``:: + + - https://myurl/abc.tar.xz : 23445 + # ^ extra space here + - https://myurl/def.tar.xz : 944 + +If you combine ``prefix_colon`` with ``top_level_colon_align``, the +top level mapping doesn't get the extra prefix. If you want that +anyway, specify ``top_level_colon_align=12`` where ``12`` has to be an +integer that is one more than length of the widest key. Document version support. diff --git a/_test/roundtrip.py b/_test/roundtrip.py index 4534a16..b9cc657 100644 --- a/_test/roundtrip.py +++ b/_test/roundtrip.py @@ -27,15 +27,16 @@ def round_trip_load(inp): return ruamel.yaml.load(dinp, ruamel.yaml.RoundTripLoader) -def round_trip_dump(data, indent=None, block_seq_indent=None): - dumper = ruamel.yaml.RoundTripDumper - return ruamel.yaml.dump(data, default_flow_style=False, Dumper=dumper, - allow_unicode=True, - indent=indent, block_seq_indent=block_seq_indent) +def round_trip_dump(data, indent=None, block_seq_indent=None, top_level_colon_align=None, + prefix_colon=None): + return ruamel.yaml.round_trip_dump(data, + indent=indent, block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, + prefix_colon=prefix_colon) def round_trip(inp, outp=None, extra=None, intermediate=None, indent=None, - block_seq_indent=None): + block_seq_indent=None, top_level_colon_align=None, prefix_colon=None): if outp is None: outp = inp doutp = dedent(outp) @@ -48,9 +49,13 @@ def round_trip(inp, outp=None, extra=None, intermediate=None, indent=None, if data[k] != v: print('{0!r} <> {1!r}'.format(data[k], v)) raise ValueError - res = round_trip_dump(data, indent=indent, block_seq_indent=block_seq_indent) + res = round_trip_dump(data, indent=indent, block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, + prefix_colon=prefix_colon) print('roundtrip data:\n', res, sep='') assert res == doutp - res = round_trip_dump(data, indent=indent, block_seq_indent=block_seq_indent) + res = round_trip_dump(data, indent=indent, block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, + prefix_colon=prefix_colon) print('roundtrip second round data:\n', res, sep='') assert res == doutp diff --git a/_test/test_indentation.py b/_test/test_indentation.py index 41f7ae9..954f231 100644 --- a/_test/test_indentation.py +++ b/_test/test_indentation.py @@ -151,6 +151,26 @@ class TestIndent: """, indent=2, block_seq_indent=2) +class TestYpkgIndent: + def test_00(self): + round_trip(""" + name : nano + version : 2.3.2 + release : 1 + homepage : http://www.nano-editor.org + source : + - http://www.nano-editor.org/dist/v2.3/nano-2.3.2.tar.gz : ff309248071486445609ad4269b798262a1324d7503dc09dea289f5b60106be8 + license : GPL-2.0 + summary : GNU nano is an easy-to-use text editor + builddeps : + - ncurses-devel + description: | + GNU nano is an easy-to-use text editor originally designed + as a replacement for Pico, the ncurses-based editor from the non-free mailer + package Pine (itself now available under the Apache License as Alpine). + """, indent=4, block_seq_indent=2, top_level_colon_align=True, prefix_colon=' ') + + def guess(s): x, y, z = load_yaml_guess_indent(dedent(s)) return y, z @@ -22,7 +22,8 @@ class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver): canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, block_seq_indent=None): + version=None, tags=None, block_seq_indent=None, + top_level_colon_align=None, prefix_colon=None): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break, @@ -42,7 +43,8 @@ class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver): canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, block_seq_indent=None): + version=None, tags=None, block_seq_indent=None, + top_level_colon_align=None, prefix_colon=None): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break, @@ -62,7 +64,8 @@ class Dumper(Emitter, Serializer, Representer, Resolver): canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, block_seq_indent=None): + version=None, tags=None, block_seq_indent=None, + top_level_colon_align=None, prefix_colon=None): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break, @@ -82,11 +85,14 @@ class RoundTripDumper(Emitter, Serializer, RoundTripRepresenter, VersionedResolv canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, block_seq_indent=None): + version=None, tags=None, block_seq_indent=None, + top_level_colon_align=None, prefix_colon=None): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break, - block_seq_indent=block_seq_indent) + block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, + prefix_colon=prefix_colon) Serializer.__init__(self, encoding=encoding, explicit_start=explicit_start, explicit_end=explicit_end, @@ -50,7 +50,8 @@ class Emitter(object): MAX_SIMPLE_KEY_LENGTH = 128 def __init__(self, stream, canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, block_seq_indent=None): + allow_unicode=None, line_break=None, block_seq_indent=None, + top_level_colon_align=None, prefix_colon=None): # The stream should have the methods `write` and possibly `flush`. self.stream = stream @@ -93,10 +94,15 @@ class Emitter(object): # Whether the document requires an explicit document indicator self.open_ended = False + # colon handling + self.colon = u':' + self.prefixed_colon = self.colon if prefix_colon is None else prefix_colon + self.colon + # Formatting details. self.canonical = canonical self.allow_unicode = allow_unicode self.block_seq_indent = block_seq_indent if block_seq_indent else 0 + self.top_level_colon_align = top_level_colon_align self.best_indent = 2 if indent and 1 < indent < 10: self.best_indent = indent @@ -162,7 +168,7 @@ class Emitter(object): return False return (len(self.events) < count+1) - def increase_indent(self, flow=False, indentless=False): + def increase_indent(self, flow=False, sequence=None, indentless=False): self.indents.append(self.indent) if self.indent is None: if flow: @@ -311,7 +317,7 @@ class Emitter(object): def expect_flow_sequence(self): self.write_indicator(u'[', True, whitespace=True) self.flow_level += 1 - self.increase_indent(flow=True) + self.increase_indent(flow=True, sequence=True) self.state = self.expect_first_flow_sequence_item def expect_first_flow_sequence_item(self): @@ -350,7 +356,7 @@ class Emitter(object): def expect_flow_mapping(self): self.write_indicator(u'{', True, whitespace=True) self.flow_level += 1 - self.increase_indent(flow=True) + self.increase_indent(flow=True, sequence=False) self.state = self.expect_first_flow_mapping_key def expect_first_flow_mapping_key(self): @@ -400,14 +406,14 @@ class Emitter(object): self.expect_node(mapping=True) def expect_flow_mapping_simple_value(self): - self.write_indicator(u':', False) + self.write_indicator(self.prefixed_colon, False) self.states.append(self.expect_flow_mapping_key) self.expect_node(mapping=True) def expect_flow_mapping_value(self): if self.canonical or self.column > self.best_width: self.write_indent() - self.write_indicator(u':', True) + self.write_indicator(self.prefixed_colon, True) self.states.append(self.expect_flow_mapping_key) self.expect_node(mapping=True) @@ -415,7 +421,7 @@ class Emitter(object): def expect_block_sequence(self): indentless = (self.mapping_context and not self.indention) - self.increase_indent(flow=False, indentless=indentless) + self.increase_indent(flow=False, sequence=True, indentless=indentless) self.state = self.expect_first_block_sequence_item def expect_first_block_sequence_item(self): @@ -440,7 +446,7 @@ class Emitter(object): # Block mapping handlers. def expect_block_mapping(self): - self.increase_indent(flow=False) + self.increase_indent(flow=False, sequence=False) self.state = self.expect_first_block_mapping_key def expect_first_block_mapping_key(self): @@ -470,13 +476,19 @@ class Emitter(object): def expect_block_mapping_simple_value(self): if getattr(self.event, 'style', None) != '?': - self.write_indicator(u':', False) + prefix = u'' + if self.indent == 0 and self.top_level_colon_align is not None: + # write non-prefixed colon + c = u' ' * (self.top_level_colon_align - self.column) + self.colon + else: + c = self.prefixed_colon + self.write_indicator(c, False) self.states.append(self.expect_block_mapping_key) self.expect_node(mapping=True) def expect_block_mapping_value(self): self.write_indent() - self.write_indicator(u':', True, indention=True) + self.write_indicator(self.prefixed_colon, True, indention=True) self.states.append(self.expect_block_mapping_key) self.expect_node(mapping=True) @@ -194,12 +194,15 @@ def dump_all(documents, stream=None, Dumper=Dumper, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=enc, explicit_start=None, explicit_end=None, - version=None, tags=None, block_seq_indent=None): + version=None, tags=None, block_seq_indent=None, + top_level_colon_align=None, prefix_colon=None): """ Serialize a sequence of Python objects into a YAML stream. If stream is None, return the produced string instead. """ getvalue = None + if top_level_colon_align is True: + top_level_colon_align = max([len(str(x)) for x in documents[0]]) if stream is None: if encoding is None: stream = StringIO() @@ -212,7 +215,8 @@ def dump_all(documents, stream=None, Dumper=Dumper, allow_unicode=allow_unicode, line_break=line_break, encoding=encoding, explicit_start=explicit_start, explicit_end=explicit_end, version=version, - tags=tags, block_seq_indent=block_seq_indent + tags=tags, block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, prefix_colon=prefix_colon, ) try: dumper.open() @@ -273,7 +277,8 @@ def round_trip_dump(data, stream=None, Dumper=RoundTripDumper, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=enc, explicit_start=None, explicit_end=None, - version=None, tags=None, block_seq_indent=None): + version=None, tags=None, block_seq_indent=None, + top_level_colon_align=None, prefix_colon=None): allow_unicode = True if allow_unicode is None else allow_unicode return dump_all([data], stream, Dumper=Dumper, default_style=default_style, @@ -284,7 +289,8 @@ def round_trip_dump(data, stream=None, Dumper=RoundTripDumper, line_break=line_break, encoding=encoding, explicit_start=explicit_start, explicit_end=explicit_end, - version=version, tags=tags, block_seq_indent=block_seq_indent) + version=version, tags=tags, block_seq_indent=block_seq_indent, + top_level_colon_align=top_level_colon_align, prefix_colon=prefix_colon) def add_implicit_resolver(tag, regexp, first=None, |