diff options
-rw-r--r-- | CHANGES | 24 | ||||
-rw-r--r-- | README.rst | 12 | ||||
-rw-r--r-- | __init__.py | 4 | ||||
-rw-r--r-- | _test/test_comments.py | 4 | ||||
-rw-r--r-- | _test/test_float.py | 6 | ||||
-rw-r--r-- | constructor.py | 2 | ||||
-rw-r--r-- | emitter.py | 7 | ||||
-rw-r--r-- | parser.py | 3 | ||||
-rw-r--r-- | representer.py | 21 | ||||
-rw-r--r-- | scalarfloat.py | 8 | ||||
-rw-r--r-- | tokens.py | 25 |
11 files changed, 69 insertions, 47 deletions
@@ -1,3 +1,27 @@ +[0, 15, 24]: 2017-08-09 + - added ScalarFloat which supports roundtripping of 23.1, 23.100, + 42.00E+56, 0.0, -0.0 etc. while keeping the format. Underscores in mantissas + are not preserved/supported (yet, is anybody using that?). + - (finally) fixed longstanding issue 23 (reported by `Antony Sottile + <https://bitbucket.org/asottile/>`_), now handling comment between block + mapping key and value correctly + - warn on YAML 1.1 float input that is incorrect (triggered by invalid YAML + provided by Cecil Curry) + - allow setting of boolean representation (`false`, `true`) by using: + ``yaml.boolean_representation = [u'False', u'True']`` + +[0, 15, 24]: 2017-08-09 + - added ScalarFloat which supports roundtripping of 23.1, 23.100, + 42.00E+56, 0.0, -0.0 etc. while keeping the format. Underscores in mantissas + are not preserved/supported (yet, is anybody using that?). + - (finally) fixed longstanding issue 23 (reported by `Antony Sottile + <https://bitbucket.org/asottile/>`_), now handling comment between block + mapping key and value correctly + - warn on YAML 1.1 float input that is incorrect (triggered by invalid YAML + provided by Cecil Curry) + - allow setting of boolean representation (`false`, `true`) by using: + ``yaml.boolean_representation = [u'False', u'True']`` + [0, 15, 23]: 2017-08-01 - fix for round_tripping integers on 2.7.X > sys.maxint (reported by ccatterina) @@ -35,6 +35,18 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key +0.15.24 (2017-08-09): + - added ScalarFloat which supports roundtripping of 23.1, 23.100, + 42.00E+56, 0.0, -0.0 etc. while keeping the format. Underscores in mantissas + are not preserved/supported (yet, is anybody using that?). + - (finally) fixed longstanding issue 23 (reported by `Antony Sottile + <https://bitbucket.org/asottile/>`_), now handling comment between block + mapping key and value correctly + - warn on YAML 1.1 float input that is incorrect (triggered by invalid YAML + provided by Cecil Curry) + - allow setting of boolean representation (`false`, `true`) by using: + ``yaml.boolean_representation = [u'False', u'True']`` + 0.15.23 (2017-08-01): - fix for round_tripping integers on 2.7.X > sys.maxint (reported by ccatterina) diff --git a/__init__.py b/__init__.py index 1ea3f6b..7e45afe 100644 --- a/__init__.py +++ b/__init__.py @@ -7,8 +7,8 @@ if False: # MYPY _package_data = dict( full_package_name='ruamel.yaml', - version_info=(0, 15, 24, 'dev'), - __version__='0.15.24.dev', + version_info=(0, 15, 24), + __version__='0.15.24', 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/_test/test_comments.py b/_test/test_comments.py index 8717727..330ab58 100644 --- a/_test/test_comments.py +++ b/_test/test_comments.py @@ -778,7 +778,6 @@ class TestEmptyValueBeforeComments: - b: 2 # comment 3 """) - @pytest.mark.xfail(strict=True) def test_issue_25_03(self): round_trip("""\ a: # comment 1 @@ -794,7 +793,6 @@ class TestEmptyValueBeforeComments: """) - test_block_scalar_commented_line_template = """\ y: p # Some comment @@ -809,7 +807,7 @@ class TestBlockScalarWithComments: # issue 99 reported by Colm O'Connor def test_scalar_with_comments(self): for x in ['', '\n', '\n# Another comment\n', '\n\n', '\n\n# abc\n#xyz\n', - '\n\n# abc\n#xyz\n', '# abc\n\n#xyz\n', '\n\n # abc\n #xyz\n']: + '\n\n# abc\n#xyz\n', '# abc\n\n#xyz\n', '\n\n # abc\n #xyz\n']: commented_line = test_block_scalar_commented_line_template.format(x) data = ruamel.yaml.round_trip_load(commented_line) diff --git a/_test/test_float.py b/_test/test_float.py index 98a1f78..498c271 100644 --- a/_test/test_float.py +++ b/_test/test_float.py @@ -4,7 +4,7 @@ from __future__ import print_function, absolute_import, division, unicode_litera import pytest # NOQA -from roundtrip import round_trip, dedent, round_trip_load, round_trip_dump +from roundtrip import round_trip, dedent, round_trip_load, round_trip_dump # NOQA from ruamel.yaml.error import MantissaNoDotYAML1_1Warning # http://yaml.org/type/int.html is where underscores in integers are defined @@ -125,7 +125,7 @@ class TestFloat: assert -41.99e-56 > d > -42.01e-56 def test_round_trip_exp_04(self): - data = round_trip("""\ + round_trip("""\ - 1.2e+34 - 1.23e+034 - 1.230e+34 @@ -136,7 +136,7 @@ class TestFloat: def test_yaml_1_1_no_dot(self): with pytest.warns(MantissaNoDotYAML1_1Warning): - data = round_trip_load("""\ + round_trip_load("""\ %YAML 1.1 --- - 1e6 diff --git a/constructor.py b/constructor.py index e91961e..dcf8e02 100644 --- a/constructor.py +++ b/constructor.py @@ -1052,7 +1052,7 @@ class RoundTripConstructor(SafeConstructor): lead0 += 1 idx += 1 return lead0 - underscore = None + # underscore = None m_sign = False # type: Any value_so = to_str(self.construct_scalar(node)) value_s = value_so.replace('_', '').lower() @@ -318,13 +318,14 @@ class Emitter(object): self.expect_scalar() elif isinstance(self.event, SequenceStartEvent): if self.event.comment: - if self.write_pre_comment(self.event): - self.indention = False - self.no_newline = True + # print(' >enc', self.event.comment, end=' ') if self.event.flow_style is False and self.event.comment: if self.write_post_comment(self.event): self.indention = False self.no_newline = True + if self.write_pre_comment(self.event): + self.indention = False + self.no_newline = True if self.flow_level or self.canonical or self.event.flow_style or \ self.check_empty_sequence(): self.expect_flow_sequence() @@ -542,7 +542,6 @@ class Parser(object): def parse_block_mapping_key(self): # type: () -> Any - next_token = self.scanner.peek_token() # print('>>>> tk', type(self), next_token, getattr(next_token, 'comment', None)) if self.scanner.check_token(KeyToken): token = self.scanner.get_token() @@ -587,7 +586,7 @@ class Parser(object): self.state = self.parse_block_mapping_key comment = token.comment if comment is None: - comment=self.scanner.peek_token().comment + comment = self.scanner.peek_token().comment return self.process_empty_scalar(token.end_mark, comment=comment) else: self.state = self.parse_block_mapping_key diff --git a/representer.py b/representer.py index ee0f49e..cd4ae49 100644 --- a/representer.py +++ b/representer.py @@ -316,8 +316,8 @@ class SafeRepresenter(BaseRepresenter): # >>> repr(1e17) # '1e17' # Unfortunately, this is not a valid float representation according - # to the definition of the `!!float` tag in YAML 1.1. We fix this by adding - # '.0' before the 'e' symbol. + # to the definition of the `!!float` tag in YAML 1.1. We fix + # this by adding '.0' before the 'e' symbol. value = value.replace(u'e', u'.0e', 1) return self.represent_scalar(u'tag:yaml.org,2002:float', value) @@ -755,6 +755,7 @@ class RoundTripRepresenter(SafeRepresenter): def represent_scalar_float(self, data): # type: (Any) -> Any + """ this is way more complicated """ value = None if data != data or (data == 0.0 and data == 1.0): value = u'.nan' @@ -775,7 +776,8 @@ class RoundTripRepresenter(SafeRepresenter): # print('dw2', data._width, prec) ms = data._m_sign if data._m_sign else u'' # -1 for the dot - value = u'{}{:0{}.{}f}'.format(ms, abs(data), data._width-len(ms), data._width-prec-1) + value = u'{}{:0{}.{}f}'.format(ms, abs(data), data._width - len(ms), + data._width - prec - 1) while len(value) < data._width: value += u'0' else: @@ -803,27 +805,24 @@ class RoundTripRepresenter(SafeRepresenter): value = m1 + m2 + data._exp + u'{:{}0{}d}'.format(e, esgn, data._e_width) elif data._prec == 0: # mantissa with trailing dot e -= len(m2) - value = m1 + m2 + u'.' + data._exp + u'{:{}0{}d}'.format(e, esgn, data._e_width) + value = m1 + m2 + u'.' + data._exp + u'{:{}0{}d}'.format( + e, esgn, data._e_width) else: if data._m_lead0 > 0: m2 = u'0' * (data._m_lead0 - 1) + m1 + m2 m1 = u'0' - m2 = m2[:-data._m_lead0] # these should be zeros + m2 = m2[:-data._m_lead0] # these should be zeros e += data._m_lead0 while len(m1) < data._prec: m1 += m2[0] m2 = m2[1:] e -= 1 - value = m1 + u'.' + m2 + data._exp + u'{:{}0{}d}'.format(e, esgn, data._e_width) + value = m1 + u'.' + m2 + data._exp + u'{:{}0{}d}'.format( + e, esgn, data._e_width) if value is None: value = to_unicode(repr(data)).lower() return self.represent_scalar(u'tag:yaml.org,2002:float', value) - #if data._width is not None: - # s = u'{:0{}d}'.format(data, data._width) - #else: - # s = format(data, 'f') - #return self.insert_underscore('', s, data._underscore) def represent_sequence(self, tag, sequence, flow_style=None): # type: (Any, Any, Any) -> Any diff --git a/scalarfloat.py b/scalarfloat.py index 4608094..7f7d26d 100644 --- a/scalarfloat.py +++ b/scalarfloat.py @@ -2,14 +2,14 @@ from __future__ import print_function, absolute_import, division, unicode_literals +import sys +from .compat import no_limit_int # NOQA + if False: # MYPY from typing import Text, Any, Dict, List # NOQA __all__ = ["ScalarFloat", "ExponentialFloat", "ExponentialCapsFloat"] -import sys -from .compat import no_limit_int # NOQA - class ScalarFloat(float): def __new__(cls, *args, **kw): @@ -74,11 +74,13 @@ class ScalarFloat(float): self, self._width, self._prec, self._m_sign, self._m_lead0, # type: ignore self._exp, self._e_width, self._e_sign), file=out) # type: ignore + class ExponentialFloat(ScalarFloat): def __new__(cls, value, width=None, underscore=None): # type: (Any, Any, Any) -> Any return ScalarFloat.__new__(cls, value, width=width, underscore=underscore) + class ExponentialCapsFloat(ScalarFloat): def __new__(cls, value, width=None, underscore=None): # type: (Any, Any, Any) -> Any @@ -6,6 +6,7 @@ if False: # MYPY SHOWLINES = True + class Token(object): __slots__ = 'start_mark', 'end_mark', '_comment', @@ -20,7 +21,7 @@ class Token(object): # hasattr('self', key)] attributes = [key for key in self.__slots__ if not key.endswith('_mark')] attributes.sort() - arguments = ', '.join(['%s=%r' % (key, getattr(self, key)) + arguments = u', '.join([u'%s=%r' % (key, getattr(self, key)) for key in attributes]) if SHOWLINES: try: @@ -58,19 +59,12 @@ class Token(object): ScalarToken that follows it empty is a special for empty values -> comment after key """ - # if self.comment is not None: - # print('mci:', self, target, getattr(self, '_comment', None), - # getattr(target, '_comment', None), empty) c = self.comment if c is None: return # don't push beyond last element if isinstance(target, StreamEndToken): return - #if isinstance(self, ValueToken) and isinstance(target, BlockEntryToken): - # if target._comment: - # target._comment[0] = c[0] - # return delattr(self, '_comment') tc = target.comment if not tc: # target comment, just insert @@ -86,14 +80,6 @@ class Token(object): tc[0] = c[0] if c[1]: tc[1] = c[1] - #if empty: - # if len(tc) == 2: - # tc.extend([None, None, c[0]]) - # elif len(tc) == 4: - # tc.append(d[0]) - # else: - # raise NotImplementedError - # nprint('mco:', self, target, target.comment, empty) return self def split_comment(self): @@ -191,9 +177,10 @@ class KeyToken(Token): __slots__ = () id = '?' - def x__repr__(self): - return 'KeyToken({})'.format( - self.start_mark.buffer[self.start_mark.index:].split(None, 1)[0]) + # def x__repr__(self): + # return 'KeyToken({})'.format( + # self.start_mark.buffer[self.start_mark.index:].split(None, 1)[0]) + class ValueToken(Token): __slots__ = () |