diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | README.rst | 11 | ||||
-rw-r--r-- | __init__.py | 4 | ||||
-rw-r--r-- | _doc/_static/pypi.svg | 2 | ||||
-rw-r--r-- | comments.py | 15 | ||||
-rw-r--r-- | constructor.py | 62 | ||||
-rw-r--r-- | util.py | 58 |
7 files changed, 87 insertions, 68 deletions
@@ -1,3 +1,6 @@ +[0, 17, 17]: 2021-10-31 + - extract timestamp matching/creation to util + [0, 17, 16]: 2021-08-28 - also handle issue 397 when comment is newline @@ -4,13 +4,13 @@ ruamel.yaml ``ruamel.yaml`` is a YAML 1.2 loader/dumper package for Python. -:version: 0.17.16 -:updated: 2021-08-28 +:version: 0.17.17 +:updated: 2021-10-31 :documentation: http://yaml.readthedocs.io :repository: https://sourceforge.net/projects/ruamel-yaml/ :pypi: https://pypi.org/project/ruamel.yaml/ -*The 0.16.13 release was the last that will tested to be working on Python 2.7. +*The 0.16.13 release was the last that was tested to be working on Python 2.7. The 0.17 series will still be tested on Python 3.5, but the 0.18 will not. The 0.17 series will also stop support for the old PyYAML functions, so a `YAML()` instance will need to be created.* @@ -72,8 +72,11 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key (with empty line) +0.17.17 (2021-10-31): + - extract timestamp matching/creation to util + 0.17.16 (2021-08-28): - - also handle issue 397 when comment is newline + - 398 also handle issue 397 when comment is newline 0.17.15 (2021-08-28): - fix issue 397, insert comment before key when a comment between key and value exists diff --git a/__init__.py b/__init__.py index 53e8b51..5124d2c 100644 --- a/__init__.py +++ b/__init__.py @@ -5,8 +5,8 @@ if False: # MYPY _package_data = dict( full_package_name='ruamel.yaml', - version_info=(0, 17, 16), - __version__='0.17.16', + version_info=(0, 17, 17), + __version__='0.17.17', 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/_static/pypi.svg b/_doc/_static/pypi.svg index c59acf1..35042d8 100644 --- a/_doc/_static/pypi.svg +++ b/_doc/_static/pypi.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.17.16</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.16</text></g> </svg> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.17.17</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.17</text></g> </svg> diff --git a/comments.py b/comments.py index 053b4f1..11ee8ad 100644 --- a/comments.py +++ b/comments.py @@ -870,12 +870,13 @@ class CommentedMap(ordereddict, CommentedBase): # probably a dict that is used for x in vals[0]: self[x] = vals[0][x] - try: - self._ok.update(vals[0].keys()) # type: ignore - except AttributeError: - # assume one argument that is a list/tuple of two element lists/tuples - for x in vals[0]: - self._ok.add(x[0]) + if vals: + try: + self._ok.update(vals[0].keys()) # type: ignore + except AttributeError: + # assume one argument that is a list/tuple of two element lists/tuples + for x in vals[0]: + self._ok.add(x[0]) if kw: self._ok.add(*kw.keys()) @@ -980,7 +981,7 @@ class CommentedMap(ordereddict, CommentedBase): # # not found in merged in stuff # ordereddict.__delitem__(self, key) # for referer in self._ref: - # referer.update_key_value(key) + # referer.update=_key_value(key) # return # # ordereddict.__setitem__(self, key, value) # merge might have different value diff --git a/constructor.py b/constructor.py index e608db4..bb4eb32 100644 --- a/constructor.py +++ b/constructor.py @@ -3,7 +3,6 @@ import datetime import base64 import binascii -import re import sys import types import warnings @@ -32,7 +31,7 @@ from ruamel.yaml.scalarint import ScalarInt, BinaryInt, OctalInt, HexInt, HexCap from ruamel.yaml.scalarfloat import ScalarFloat from ruamel.yaml.scalarbool import ScalarBoolean from ruamel.yaml.timestamp import TimeStamp -from ruamel.yaml.util import RegExp +from ruamel.yaml.util import timestamp_regexp, create_timestamp if False: # MYPY from typing import Any, Dict, List, Set, Generator, Union, Optional # NOQA @@ -554,19 +553,7 @@ class SafeConstructor(BaseConstructor): node.start_mark, ) - timestamp_regexp = RegExp( - """^(?P<year>[0-9][0-9][0-9][0-9]) - -(?P<month>[0-9][0-9]?) - -(?P<day>[0-9][0-9]?) - (?:((?P<t>[Tt])|[ \\t]+) # explictly not retaining extra spaces - (?P<hour>[0-9][0-9]?) - :(?P<minute>[0-9][0-9]) - :(?P<second>[0-9][0-9]) - (?:\\.(?P<fraction>[0-9]*))? - (?:[ \\t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?) - (?::(?P<tz_minute>[0-9][0-9]))?))?)?$""", - re.X, - ) + timestamp_regexp = timestamp_regexp # moved to util 0.17.17 def construct_yaml_timestamp(self, node, values=None): # type: (Any, Any) -> Any @@ -583,42 +570,7 @@ class SafeConstructor(BaseConstructor): node.start_mark, ) values = match.groupdict() - year = int(values['year']) - month = int(values['month']) - day = int(values['day']) - if not values['hour']: - return datetime.date(year, month, day) - hour = int(values['hour']) - minute = int(values['minute']) - second = int(values['second']) - fraction = 0 - if values['fraction']: - fraction_s = values['fraction'][:6] - while len(fraction_s) < 6: - fraction_s += '0' - fraction = int(fraction_s) - if len(values['fraction']) > 6 and int(values['fraction'][6]) > 4: - fraction += 1 - delta = None - if values['tz_sign']: - tz_hour = int(values['tz_hour']) - minutes = values['tz_minute'] - tz_minute = int(minutes) if minutes else 0 - delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute) - if values['tz_sign'] == '-': - delta = -delta - # should do something else instead (or hook this up to the preceding if statement - # in reverse - # if delta is None: - # return datetime.datetime(year, month, day, hour, minute, second, fraction) - # return datetime.datetime(year, month, day, hour, minute, second, fraction, - # datetime.timezone.utc) - # the above is not good enough though, should provide tzinfo. In Python3 that is easily - # doable drop that kind of support for Python2 as it has not native tzinfo - data = datetime.datetime(year, month, day, hour, minute, second, fraction) - if delta: - data -= delta - return data + return create_timestamp(**values) def construct_yaml_omap(self, node): # type: (Any) -> Any @@ -1799,12 +1751,14 @@ class RoundTripConstructor(SafeConstructor): ) values = match.groupdict() if not values['hour']: - return SafeConstructor.construct_yaml_timestamp(self, node, values) + return create_timestamp(**values) + # return SafeConstructor.construct_yaml_timestamp(self, node, values) for part in ['t', 'tz_sign', 'tz_hour', 'tz_minute']: if values[part]: break else: - return SafeConstructor.construct_yaml_timestamp(self, node, values) + return create_timestamp(**values) + # return SafeConstructor.construct_yaml_timestamp(self, node, values) year = int(values['year']) month = int(values['month']) day = int(values['day']) @@ -1827,7 +1781,7 @@ class RoundTripConstructor(SafeConstructor): delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute) if values['tz_sign'] == '-': delta = -delta - # shold check for NOne and solve issue 366 should be tzinfo=delta) + # should check for None and solve issue 366 should be tzinfo=delta) if delta: dt = datetime.datetime(year, month, day, hour, minute) dt -= delta @@ -4,6 +4,7 @@ some helper functions that might be generally useful """ +import datetime from functools import partial import re @@ -48,6 +49,63 @@ class LazyEval: RegExp = partial(LazyEval, re.compile) +timestamp_regexp = RegExp( + """^(?P<year>[0-9][0-9][0-9][0-9]) + -(?P<month>[0-9][0-9]?) + -(?P<day>[0-9][0-9]?) + (?:((?P<t>[Tt])|[ \\t]+) # explictly not retaining extra spaces + (?P<hour>[0-9][0-9]?) + :(?P<minute>[0-9][0-9]) + :(?P<second>[0-9][0-9]) + (?:\\.(?P<fraction>[0-9]*))? + (?:[ \\t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?) + (?::(?P<tz_minute>[0-9][0-9]))?))?)?$""", + re.X, +) + + +def create_timestamp( + year, month, day, t, hour, minute, second, fraction, tz, tz_sign, tz_hour, tz_minute +): + year = int(year) + month = int(month) + day = int(day) + if not hour: + return datetime.date(year, month, day) + hour = int(hour) + minute = int(minute) + second = int(second) + if fraction: + frac = 0 + frac_s = fraction[:6] + while len(frac_s) < 6: + frac_s += '0' + frac = int(frac_s) + if len(fraction) > 6 and int(fraction[6]) > 4: + frac += 1 + fraction = frac + else: + fraction = 0 + delta = None + if tz_sign: + tz_hour = int(tz_hour) + tz_minute = int(tz_minute) if tz_minute else 0 + delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute) + if tz_sign == '-': + delta = -delta + # should do something else instead (or hook this up to the preceding if statement + # in reverse + # if delta is None: + # return datetime.datetime(year, month, day, hour, minute, second, fraction) + # return datetime.datetime(year, month, day, hour, minute, second, fraction, + # datetime.timezone.utc) + # the above is not good enough though, should provide tzinfo. In Python3 that is easily + # doable drop that kind of support for Python2 as it has not native tzinfo + data = datetime.datetime(year, month, day, hour, minute, second, fraction) + if delta: + data -= delta + return data + # originally as comment # https://github.com/pre-commit/pre-commit/pull/211#issuecomment-186466605 |