summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2016-04-14 15:52:40 +0200
committerAnthon van der Neut <anthon@mnt.org>2016-04-14 15:52:40 +0200
commit879d6d4e99f31436e2a9a9aed84c96817e766431 (patch)
treef34316628998e6e5ee83908e7387ab5b896f42dc
parent9fd5fa35ed5aae678af14f2dbeed8f1a06e775b0 (diff)
downloadruamel.yaml-879d6d4e99f31436e2a9a9aed84c96817e766431.tar.gz
added top_level_colon_align/prefix_colon0.11.9
-rw-r--r--__init__.py2
-rw-r--r--_doc/detail.rst26
-rw-r--r--_test/roundtrip.py21
-rw-r--r--_test/test_indentation.py20
-rw-r--r--dumper.py16
-rw-r--r--emitter.py32
-rw-r--r--main.py14
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
diff --git a/dumper.py b/dumper.py
index aeb6b80..90e2ca9 100644
--- a/dumper.py
+++ b/dumper.py
@@ -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,
diff --git a/emitter.py b/emitter.py
index 7e9da98..3365210 100644
--- a/emitter.py
+++ b/emitter.py
@@ -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)
diff --git a/main.py b/main.py
index 48f8020..e0041bc 100644
--- a/main.py
+++ b/main.py
@@ -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,