summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/test_comments.py8
-rw-r--r--_test/test_z_data.py3
-rw-r--r--anchor.py2
-rw-r--r--comments.py34
-rw-r--r--compat.py7
-rw-r--r--composer.py2
-rw-r--r--constructor.py2
-rw-r--r--emitter.py37
-rw-r--r--error.py4
-rw-r--r--events.py36
-rw-r--r--main.py6
-rw-r--r--nodes.py2
-rw-r--r--parser.py27
-rw-r--r--reader.py2
-rw-r--r--representer.py2
-rw-r--r--resolver.py2
-rw-r--r--scanner.py16
-rw-r--r--serializer.py2
-rw-r--r--tokens.py134
-rw-r--r--util.py2
20 files changed, 240 insertions, 90 deletions
diff --git a/_test/test_comments.py b/_test/test_comments.py
index 3173995..dbf035d 100644
--- a/_test/test_comments.py
+++ b/_test/test_comments.py
@@ -813,6 +813,14 @@ class TestEmptyValueBeforeComments:
- []
""")
+ def test_comment_after_block_scalar_indicator(self):
+ round_trip("""\
+ a: | # abc
+ test 1
+ test 2
+ # all done
+ """)
+
test_block_scalar_commented_line_template = """\
y: p
diff --git a/_test/test_z_data.py b/_test/test_z_data.py
index e48e9d5..965eb3d 100644
--- a/_test/test_z_data.py
+++ b/_test/test_z_data.py
@@ -89,6 +89,9 @@ def pytest_generate_tests(metafunc):
if os.environ.get('RUAMELAUTOTEST') == '1':
if path.parent.stem != 'debug':
continue
+ elif path.parent.stem == 'debug':
+ # don't test debug entries for production
+ continue
stem = path.stem
if stem.startswith('.#'): # skip emacs temporary file
continue
diff --git a/anchor.py b/anchor.py
index a501416..1deea78 100644
--- a/anchor.py
+++ b/anchor.py
@@ -5,7 +5,7 @@ if False: # MYPY
anchor_attrib = '_yaml_anchor'
-class Anchor(object):
+class Anchor:
__slots__ = 'value', 'always_dump'
attrib = anchor_attrib
diff --git a/comments.py b/comments.py
index 62dfe3f..d133299 100644
--- a/comments.py
+++ b/comments.py
@@ -23,9 +23,25 @@ if False: # MYPY
# fmt: off
__all__ = ['CommentedSeq', 'CommentedKeySeq',
'CommentedMap', 'CommentedOrderedMap',
- 'CommentedSet', 'comment_attrib', 'merge_attrib']
+ 'CommentedSet', 'comment_attrib', 'merge_attrib',
+ 'C_POST', 'C_PRE', 'C_SPLIT_ON_FIRST_BLANK', 'C_BLANK_LINE_PRESERVE_SPACE',
+ ]
# fmt: on
+# splitting of comments by the scanner
+# an EOLC (End-Of-Line Comment) is preceded by some token
+# an FLC (Full Line Comment) is a comment not preceded by a token, i.e. # is first non-blank on line
+# a BL is a blank line i.e. empty or spaces/tabs only
+# bits 0 and 1 are combined, you can choose only one
+C_POST = 0b00
+C_PRE = 0b01
+C_SPLIT_ON_FIRST_BLANK = 0b10 # as C_POST, but if blank line then C_PRE everything before first
+ # blank goes to POST even if no following real FLC
+# 0b11 -> reserved for future use
+C_BLANK_LINE_PRESERVE_SPACE = 0b100
+# C_EOL_PRESERVE_SPACE2 = 0b1000
+
+
comment_attrib = '_yaml_comment'
format_attrib = '_yaml_format'
line_col_attrib = '_yaml_line_col'
@@ -33,7 +49,7 @@ merge_attrib = '_yaml_merge'
tag_attrib = '_yaml_tag'
-class Comment(object):
+class Comment:
# using sys.getsize tested the Comment objects, __slots__ makes them bigger
# and adding self.end did not matter
__slots__ = 'comment', '_items', '_end', '_start'
@@ -127,7 +143,7 @@ def NoComment():
pass
-class Format(object):
+class Format:
__slots__ = ('_flow_style',)
attrib = format_attrib
@@ -154,7 +170,7 @@ class Format(object):
return self._flow_style
-class LineCol(object):
+class LineCol:
"""
line and column information wrt document, values start at zero (0)
"""
@@ -205,7 +221,7 @@ class LineCol(object):
return _F('LineCol({line}, {col})', line=self.line, col=self.col)
-class Tag(object):
+class Tag:
"""store tag information for roundtripping"""
__slots__ = ('value',)
@@ -220,7 +236,7 @@ class Tag(object):
return '{0.__class__.__name__}({0.value!r})'.format(self)
-class CommentedBase(object):
+class CommentedBase:
@property
def ca(self):
# type: () -> Any
@@ -274,7 +290,7 @@ class CommentedBase(object):
c = com.strip()
if len(c) > 0 and c[0] != '#':
com = '# ' + com
- pre_comments.append(CommentToken(com + '\n', start_mark, None))
+ pre_comments.append(CommentToken(com + '\n', start_mark))
def yaml_set_comment_before_after_key(
self, key, before=None, indent=0, after=None, after_indent=None
@@ -289,7 +305,7 @@ class CommentedBase(object):
def comment_token(s, mark):
# type: (Any, Any) -> Any
# handle empty lines as having no comment
- return CommentToken(('# ' if s else "") + s + '\n', mark, None)
+ return CommentToken(('# ' if s else "") + s + '\n', mark)
if after_indent is None:
after_indent = indent + 2
@@ -343,7 +359,7 @@ class CommentedBase(object):
comment = ' ' + comment
column = 0
start_mark = CommentMark(column)
- ct = [CommentToken(comment, start_mark, None), None]
+ ct = [CommentToken(comment, start_mark), None]
self._yaml_add_eol_comment(ct, key=key)
@property
diff --git a/compat.py b/compat.py
index 7a419dc..10ebc23 100644
--- a/compat.py
+++ b/compat.py
@@ -95,7 +95,7 @@ if 'RUAMELDEBUG' in os.environ:
if bool(_debug):
- class ObjectCounter(object):
+ class ObjectCounter:
def __init__(self):
# type: () -> None
self.map = {} # type: Dict[Any, Any]
@@ -128,7 +128,7 @@ def dbg(val=None):
return _debug & val
-class Nprint(object):
+class Nprint:
def __init__(self, file_name=None):
# type: (Any) -> None
self._max_print = None # type: Any
@@ -162,6 +162,9 @@ class Nprint(object):
self._max_print = i
self._count = None
+ def fp(self, mode='a'):
+ out = sys.stdout if self._file_name is None else open(self._file_name, mode)
+ return out
nprint = Nprint()
nprintf = Nprint('/var/tmp/ruamel.yaml.log')
diff --git a/composer.py b/composer.py
index c47c85d..1d7fc65 100644
--- a/composer.py
+++ b/composer.py
@@ -27,7 +27,7 @@ class ComposerError(MarkedYAMLError):
pass
-class Composer(object):
+class Composer:
def __init__(self, loader=None):
# type: (Any) -> None
self.loader = loader
diff --git a/constructor.py b/constructor.py
index 3fddba6..7b7426f 100644
--- a/constructor.py
+++ b/constructor.py
@@ -52,7 +52,7 @@ class DuplicateKeyError(MarkedYAMLFutureWarning):
pass
-class BaseConstructor(object):
+class BaseConstructor:
yaml_constructors = {} # type: Dict[Any, Any]
yaml_multi_constructors = {} # type: Dict[Any, Any]
diff --git a/emitter.py b/emitter.py
index 9f37906..afbffc4 100644
--- a/emitter.py
+++ b/emitter.py
@@ -13,7 +13,7 @@ from ruamel.yaml.events import * # NOQA
# fmt: off
from ruamel.yaml.compat import _F, nprint, dbg, DBG_EVENT, \
- check_anchorname_char
+ check_anchorname_char, nprintf
# fmt: on
if False: # MYPY
@@ -27,7 +27,7 @@ class EmitterError(YAMLError):
pass
-class ScalarAnalysis(object):
+class ScalarAnalysis:
def __init__(
self,
scalar,
@@ -50,7 +50,7 @@ class ScalarAnalysis(object):
self.allow_block = allow_block
-class Indents(object):
+class Indents:
# replacement for the list based stack of None/int
def __init__(self):
# type: () -> None
@@ -87,7 +87,7 @@ class Indents(object):
return len(self.values)
-class Emitter(object):
+class Emitter:
# fmt: off
DEFAULT_TAG_PREFIXES = {
'!': '!',
@@ -905,7 +905,12 @@ class Emitter(object):
# comment following a folded scalar must dedent (issue 376)
self.event.comment[0].column = self.indent - 1
elif self.style == '|':
- self.write_literal(self.analysis.scalar, self.event.comment)
+ # self.write_literal(self.analysis.scalar, self.event.comment)
+ try:
+ cmx = self.event.comment[1][0]
+ except (IndexError, TypeError):
+ cmx = ""
+ self.write_literal(self.analysis.scalar, cmx)
if (
self.event.comment
and self.event.comment[0]
@@ -1557,13 +1562,21 @@ class Emitter(object):
def write_literal(self, text, comment=None):
# type: (Any, Any) -> None
hints, _indent, _indicator = self.determine_block_hints(text)
- self.write_indicator('|' + hints, True)
- try:
- comment = comment[1][0]
- if comment:
- self.stream.write(comment)
- except (TypeError, IndexError):
- pass
+ #if comment is not None:
+ # try:
+ # hints += comment[1][0]
+ # except (TypeError, IndexError) as e:
+ # pass
+ if not isinstance(comment, str):
+ comment = ''
+ self.write_indicator('|' + hints + comment, True)
+ #try:
+ # nprintf('selfev', comment)
+ # cmx = comment[1][0]
+ # if cmx:
+ # self.stream.write(cmx)
+ #except (TypeError, IndexError) as e:
+ # pass
if _indicator == '+':
self.open_ended = True
self.write_line_break()
diff --git a/error.py b/error.py
index 04c4c24..30b114a 100644
--- a/error.py
+++ b/error.py
@@ -22,7 +22,7 @@ __all__ = [
]
-class StreamMark(object):
+class StreamMark:
__slots__ = 'name', 'index', 'line', 'column'
def __init__(self, name, index, line, column):
@@ -128,7 +128,7 @@ class StringMark(StreamMark):
return where
-class CommentMark(object):
+class CommentMark:
__slots__ = ('column',)
def __init__(self, column):
diff --git a/events.py b/events.py
index 0e44d8d..ef63dad 100644
--- a/events.py
+++ b/events.py
@@ -13,7 +13,7 @@ def CommentCheck():
pass
-class Event(object):
+class Event:
__slots__ = 'start_mark', 'end_mark', 'comment'
def __init__(self, start_mark=None, end_mark=None, comment=CommentCheck):
@@ -27,18 +27,30 @@ class Event(object):
def __repr__(self):
# type: () -> Any
- attributes = [
- key
- for key in ['anchor', 'tag', 'implicit', 'value', 'flow_style', 'style']
- if hasattr(self, key)
- ]
- arguments = ', '.join(
- [_F('{key!s}={attr!r}', key=key, attr=getattr(self, key)) for key in attributes]
- )
- if self.comment not in [None, CommentCheck]:
- arguments += ', comment={!r}'.format(self.comment)
+ if True:
+ arguments = []
+ if hasattr(self, 'value'):
+ arguments.append(repr(getattr(self, 'value')))
+ for key in ['anchor', 'tag', 'implicit', 'flow_style', 'style']:
+ v = getattr(self, key, None)
+ if v is not None:
+ arguments.append(_F('{key!s}={v!r}', key=key, v=v))
+ if self.comment not in [None, CommentCheck]:
+ arguments.append('comment={!r}'.format(self.comment))
+ arguments = ', '.join(arguments)
+ else:
+ attributes = [
+ key
+ for key in ['anchor', 'tag', 'implicit', 'value', 'flow_style', 'style']
+ if hasattr(self, key)
+ ]
+ arguments = ', '.join(
+ [_F('{key!s}={attr!r}', key=key, attr=getattr(self, key)) for key in attributes]
+ )
+ if self.comment not in [None, CommentCheck]:
+ arguments += ', comment={!r}'.format(self.comment)
return _F(
- '{self_class_name!s}{arguments!s}',
+ '{self_class_name!s}({arguments!s})',
self_class_name=self.__class__.__name__,
arguments=arguments,
)
diff --git a/main.py b/main.py
index efde0e1..7d2f177 100644
--- a/main.py
+++ b/main.py
@@ -16,7 +16,7 @@ from ruamel.yaml.nodes import * # NOQA
from ruamel.yaml.loader import BaseLoader, SafeLoader, Loader, RoundTripLoader # NOQA
from ruamel.yaml.dumper import BaseDumper, SafeDumper, Dumper, RoundTripDumper # NOQA
-from ruamel.yaml.compat import StringIO, BytesIO, with_metaclass, nprint
+from ruamel.yaml.compat import StringIO, BytesIO, with_metaclass, nprint, nprintf
from ruamel.yaml.resolver import VersionedResolver, Resolver # NOQA
from ruamel.yaml.representer import (
BaseRepresenter,
@@ -49,7 +49,7 @@ except: # NOQA
# subset of abbreviations, which should be all caps according to PEP8
-class YAML(object):
+class YAML:
def __init__(self, *, typ=None, pure=False, output=None, plug_ins=None): # input=None,
# type: (Any, Optional[Text], Any, Any, Any) -> None
"""
@@ -825,7 +825,7 @@ class YAML(object):
self.compact_seq_map = seq_map
-class YAMLContextManager(object):
+class YAMLContextManager:
def __init__(self, yaml, transform=None):
# type: (Any, Any) -> None # used to be: (Any, Optional[Callable]) -> None
self._yaml = yaml
diff --git a/nodes.py b/nodes.py
index f51f989..0efe3ff 100644
--- a/nodes.py
+++ b/nodes.py
@@ -8,7 +8,7 @@ if False: # MYPY
from typing import Dict, Any, Text # NOQA
-class Node(object):
+class Node:
__slots__ = 'tag', 'value', 'start_mark', 'end_mark', 'comment', 'anchor'
def __init__(self, tag, value, start_mark, end_mark, comment=None, anchor=None):
diff --git a/parser.py b/parser.py
index 76c089b..279fc20 100644
--- a/parser.py
+++ b/parser.py
@@ -90,7 +90,7 @@ class ParserError(MarkedYAMLError):
pass
-class Parser(object):
+class Parser:
# Since writing a recursive-descendant parser is a straightforward task, we
# do not give many comments here.
@@ -171,7 +171,7 @@ class Parser(object):
# type: () -> Any
# Parse the stream start.
token = self.scanner.get_token()
- token.move_comment(self.scanner.peek_token())
+ self.move_token_comment(token)
event = StreamStartEvent(token.start_mark, token.end_mark, encoding=token.encoding)
# Prepare the next state.
@@ -357,7 +357,7 @@ class Parser(object):
start_mark = end_mark = tag_mark = None
if self.scanner.check_token(AnchorToken):
token = self.scanner.get_token()
- token.move_comment(self.scanner.peek_token())
+ self.move_token_comment(token)
start_mark = token.start_mark
end_mark = token.end_mark
anchor = token.value
@@ -467,7 +467,7 @@ class Parser(object):
comment = pt.comment
# nprint('pt0', type(pt))
if comment is None or comment[1] is None:
- comment = pt.split_comment()
+ comment = pt.split_old_comment()
# nprint('pt1', comment)
event = SequenceStartEvent(
anchor, tag, implicit, start_mark, end_mark, flow_style=False, comment=comment
@@ -506,7 +506,7 @@ class Parser(object):
# type: () -> Any
token = self.scanner.get_token()
# move any comment from start token
- # token.move_comment(self.scanner.peek_token())
+ # self.move_token_comment(token)
self.marks.append(token.start_mark)
return self.parse_block_sequence_entry()
@@ -514,7 +514,7 @@ class Parser(object):
# type: () -> Any
if self.scanner.check_token(BlockEntryToken):
token = self.scanner.get_token()
- token.move_comment(self.scanner.peek_token())
+ self.move_token_comment(token)
if not self.scanner.check_token(BlockEntryToken, BlockEndToken):
self.states.append(self.parse_block_sequence_entry)
return self.parse_block_node()
@@ -546,7 +546,7 @@ class Parser(object):
# type: () -> Any
if self.scanner.check_token(BlockEntryToken):
token = self.scanner.get_token()
- token.move_comment(self.scanner.peek_token())
+ self.move_token_comment(token)
if not self.scanner.check_token(
BlockEntryToken, KeyToken, ValueToken, BlockEndToken
):
@@ -575,7 +575,7 @@ class Parser(object):
# type: () -> Any
if self.scanner.check_token(KeyToken):
token = self.scanner.get_token()
- token.move_comment(self.scanner.peek_token())
+ self.move_token_comment(token)
if not self.scanner.check_token(KeyToken, ValueToken, BlockEndToken):
self.states.append(self.parse_block_mapping_value)
return self.parse_block_node_or_indentless_sequence()
@@ -594,7 +594,7 @@ class Parser(object):
token.start_mark,
)
token = self.scanner.get_token()
- token.move_comment(self.scanner.peek_token())
+ self.move_token_comment(token)
event = MappingEndEvent(token.start_mark, token.end_mark, comment=token.comment)
self.state = self.states.pop()
self.marks.pop()
@@ -606,10 +606,10 @@ class Parser(object):
token = self.scanner.get_token()
# value token might have post comment move it to e.g. block
if self.scanner.check_token(ValueToken):
- token.move_comment(self.scanner.peek_token())
+ self.move_token_comment(token)
else:
if not self.scanner.check_token(KeyToken):
- token.move_comment(self.scanner.peek_token(), empty=True)
+ self.move_token_comment(token, empty=True)
# else: empty value for this key cannot move token.comment
if not self.scanner.check_token(KeyToken, ValueToken, BlockEndToken):
self.states.append(self.parse_block_mapping_key)
@@ -782,6 +782,11 @@ class Parser(object):
# type: (Any, Any) -> Any
return ScalarEvent(None, None, (True, False), "", mark, mark, comment=comment)
+ def move_token_comment(self, token, nt=None, empty=False):
+ if getattr(self.loader, 'comment_handling', None) is None: # pre 0.18
+ token.move_old_comment(self.scanner.peek_token() if nt is None else nt, empty=empty)
+ else:
+ token.move_new_comment(self.scanner.peek_token() if nt is None else nt, empty=empty)
class RoundTripParser(Parser):
"""roundtrip is a safe loader, that wants to see the unmangled tag"""
diff --git a/reader.py b/reader.py
index 3a1656a..ff62135 100644
--- a/reader.py
+++ b/reader.py
@@ -65,7 +65,7 @@ class ReaderError(YAMLError):
)
-class Reader(object):
+class Reader:
# Reader:
# - determines the data encoding and converts it to a unicode string,
# - checks if characters are in allowed range,
diff --git a/representer.py b/representer.py
index 32e6f58..f3e3e43 100644
--- a/representer.py
+++ b/representer.py
@@ -47,7 +47,7 @@ class RepresenterError(YAMLError):
pass
-class BaseRepresenter(object):
+class BaseRepresenter:
yaml_representers = {} # type: Dict[Any, Any]
yaml_multi_representers = {} # type: Dict[Any, Any]
diff --git a/resolver.py b/resolver.py
index eab6163..a6c97df 100644
--- a/resolver.py
+++ b/resolver.py
@@ -101,7 +101,7 @@ class ResolverError(YAMLError):
pass
-class BaseResolver(object):
+class BaseResolver:
DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str'
DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq'
diff --git a/scanner.py b/scanner.py
index 547af3c..f98da00 100644
--- a/scanner.py
+++ b/scanner.py
@@ -28,9 +28,10 @@
# Read comments in the Scanner code for more details.
#
-from ruamel.yaml.error import MarkedYAMLError
+import inspect
+from ruamel.yaml.error import MarkedYAMLError, CommentMark
from ruamel.yaml.tokens import * # NOQA
-from ruamel.yaml.compat import _F, check_anchorname_char, nprint # NOQA
+from ruamel.yaml.compat import _F, check_anchorname_char, nprint, nprintf # NOQA
if False: # MYPY
from typing import Any, Dict, Optional, List, Union, Text # NOQA
@@ -48,7 +49,7 @@ class ScannerError(MarkedYAMLError):
pass
-class SimpleKey(object):
+class SimpleKey:
# See below simple keys treatment.
def __init__(self, token_number, required, index, line, column, mark):
@@ -61,7 +62,7 @@ class SimpleKey(object):
self.mark = mark
-class Scanner(object):
+class Scanner:
def __init__(self, loader=None):
# type: (Any) -> None
"""Initialize the scanner."""
@@ -1972,10 +1973,3 @@ class RoundTripScanner(Scanner):
def scan_block_scalar(self, style, rt=True):
# type: (Any, Optional[bool]) -> Any
return Scanner.scan_block_scalar(self, style, rt=rt)
-
-
-# try:
-# import psyco
-# psyco.bind(Scanner)
-# except ImportError:
-# pass
diff --git a/serializer.py b/serializer.py
index 19b0424..1a78829 100644
--- a/serializer.py
+++ b/serializer.py
@@ -29,7 +29,7 @@ class SerializerError(YAMLError):
pass
-class Serializer(object):
+class Serializer:
# 'id' and 3+ numbers, but not 000
ANCHOR_TEMPLATE = 'id%03d'
diff --git a/tokens.py b/tokens.py
index 19a2572..490866b 100644
--- a/tokens.py
+++ b/tokens.py
@@ -6,10 +6,10 @@ if False: # MYPY
from typing import Text, Any, Dict, Optional, List # NOQA
from .error import StreamMark # NOQA
-SHOWLINES = True
+SHOW_LINES = True
-class Token(object):
+class Token:
__slots__ = 'start_mark', 'end_mark', '_comment'
def __init__(self, start_mark, end_mark):
@@ -23,19 +23,20 @@ class Token(object):
# hasattr('self', key)]
attributes = [key for key in self.__slots__ if not key.endswith('_mark')]
attributes.sort()
- arguments = ', '.join(
- [_F('{key!s}={gattr!r})', key=key, gattr=getattr(self, key)) for key in attributes]
- )
- if SHOWLINES:
+ #arguments = ', '.join(
+ # [_F('{key!s}={gattr!r})', key=key, gattr=getattr(self, key)) for key in attributes]
+ #)
+ arguments = [_F('{key!s}={gattr!r}', key=key, gattr=getattr(self, key)) for key in attributes]
+ if SHOW_LINES:
try:
- arguments += ', line: ' + str(self.start_mark.line)
+ arguments.append('line: ' + str(self.start_mark.line))
except: # NOQA
pass
try:
- arguments += ', comment: ' + str(self._comment)
+ arguments.append('comment: ' + str(self._comment))
except: # NOQA
pass
- return '{}({})'.format(self.__class__.__name__, arguments)
+ return '{}({})'.format(self.__class__.__name__, ', '.join(arguments))
@property
def column(self):
@@ -45,29 +46,77 @@ class Token(object):
def column(self, pos):
self.start_mark.column = pos
+ # old style ( <= 0.17) is a TWO element list with first being the EOL
+ # comment concatenated with following FLC/BLNK; and second being a list of FLC/BLNK
+ # preceding the token
+ # new style ( >= 0.17 ) is a THREE element list with the first being a list of
+ # preceding FLC/BLNK, the second EOL and the third following FLC/BLNK
+ # note that new style has differing order, and does not consist of CommentToken(s)
+ # but of CommentInfo instances
+ # any non-assigned values in new style are None, but first and last can be empty list
+ # new style routines add one comment at a time
+
+ # going to be deprecated in favour of add_comment_eol/post
def add_post_comment(self, comment):
# type: (Any) -> None
if not hasattr(self, '_comment'):
self._comment = [None, None]
+ else:
+ assert len(self._comment) == 2 # make sure it is version 0
+ #if isinstance(comment, CommentToken):
+ # if comment.value.startswith('# C09'):
+ # raise
self._comment[0] = comment
+ # going to be deprecated in favour of add_comment_pre
def add_pre_comments(self, comments):
# type: (Any) -> None
if not hasattr(self, '_comment'):
self._comment = [None, None]
+ else:
+ assert len(self._comment) == 2 # make sure it is version 0
assert self._comment[1] is None
self._comment[1] = comments
+ return
- def get_comment(self):
- # type: () -> Any
- return getattr(self, '_comment', None)
+ # new style
+ def add_comment_pre(self, comment):
+ if not hasattr(self, '_comment'):
+ self._comment = [[], None, None]
+ else:
+ assert len(self._comment) == 3
+ if self._comment[0] is None:
+ self._comment[0] = []
+ self._comment[0].append(comment)
+
+ def add_comment_eol(self, comment):
+ if not hasattr(self, '_comment'):
+ self._comment = [None, None, None]
+ else:
+ assert len(self._comment) == 3
+ assert self._comment[1] is None
+ self._comment[1] = comment
+
+ def add_comment_post(self, comment):
+ if not hasattr(self, '_comment'):
+ self._comment = [None, None, []]
+ else:
+ assert len(self._comment) == 3
+ if self._comment[2] is None:
+ self._comment[2] = []
+ self._comment[2].append(comment)
+
+
+ #def get_comment(self):
+ # # type: () -> Any
+ # return getattr(self, '_comment', None)
@property
def comment(self):
# type: () -> Any
return getattr(self, '_comment', None)
- def move_comment(self, target, empty=False):
+ def move_old_comment(self, target, empty=False):
# type: (Any, bool) -> Any
"""move a comment from this token to target (normally next token)
used to combine e.g. comments before a BlockEntryToken to the
@@ -97,7 +146,7 @@ class Token(object):
tc[1] = c[1]
return self
- def split_comment(self):
+ def split_old_comment(self):
# type: () -> Any
""" split the post part of a comment, and return it
as comment to be added. Delete second part if [None, None]
@@ -113,6 +162,40 @@ class Token(object):
delattr(self, '_comment')
return ret_val
+ def move_new_comment(self, target, empty=False):
+ # type: (Any, bool) -> Any
+ """move a comment from this token to target (normally next token)
+ used to combine e.g. comments before a BlockEntryToken to the
+ ScalarToken that follows it
+ empty is a special for empty values -> comment after key
+ """
+ c = self.comment
+ if c is None:
+ return
+ # don't push beyond last element
+ if isinstance(target, (StreamEndToken, DocumentStartToken)):
+ return
+ delattr(self, '_comment')
+ tc = target.comment
+ if not tc: # target comment, just insert
+ # special for empty value in key: value issue 25
+ if empty:
+ c = [c[0], c[1], c[2]]
+ target._comment = c
+ # nprint('mco2:', self, target, target.comment, empty)
+ return self
+ return
+ raise NotImplemtedError
+ # if self and target have both pre, eol or post comments, something seems wrong
+ for idx in range(3):
+ if c[idx] and tc[idx]:
+ raise NotImplementedError(_F('overlap in comment {c!r} {tc!r}', c=c, tc=tc))
+ # move the comment parts
+ for idx in range(3):
+ if c[idx]:
+ tc[idx] = c[idx]
+ return self
+
# class BOMToken(Token):
# id = '<byte order mark>'
@@ -256,13 +339,26 @@ class ScalarToken(Token):
class CommentToken(Token):
- __slots__ = 'value', 'pre_done'
+ __slots__ = '_value', 'pre_done'
id = '<comment>'
- def __init__(self, value, start_mark, end_mark):
+ def __init__(self, value, start_mark=None, end_mark=None, column=None):
# type: (Any, Any, Any) -> None
- Token.__init__(self, start_mark, end_mark)
- self.value = value
+ if start_mark is None:
+ assert columns is not None
+ self._column = column
+ Token.__init__(self, start_mark, None)
+ self._value = value
+
+ @property
+ def value(self):
+ if isinstance(self._value, str):
+ return self._value
+ return "".join(self._value)
+
+ @value.setter
+ def value(self, val):
+ self._value = val
def reset(self):
# type: () -> None
@@ -272,7 +368,7 @@ class CommentToken(Token):
def __repr__(self):
# type: () -> Any
v = '{!r}'.format(self.value)
- if SHOWLINES:
+ if SHOW_LINES:
try:
v += ', line: ' + str(self.start_mark.line)
except: # NOQA
diff --git a/util.py b/util.py
index 1f0b71b..869aaef 100644
--- a/util.py
+++ b/util.py
@@ -13,7 +13,7 @@ if False: # MYPY
from .compat import StreamTextType # NOQA
-class LazyEval(object):
+class LazyEval:
"""
Lightweight wrapper around lazily evaluated func(*args, **kwargs).