diff options
author | Anthon van der Neut <anthon@mnt.org> | 2014-11-23 11:31:53 +0100 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2014-11-23 11:31:53 +0100 |
commit | d709fb8be80a54e793f7eb5a148cd1fa5103933c (patch) | |
tree | e50bc28652738b8d7940b85eb90d2fd828dde932 | |
parent | 259d7c875079984ed502912fe77868f5b435e36b (diff) | |
download | ruamel.yaml-d709fb8be80a54e793f7eb5a148cd1fa5103933c.tar.gz |
- change install so that you can include ruamel.yaml instead of ruamel.yaml.py
- add "yaml" utility with initial subcommands (test rt, from json)
-rw-r--r-- | README.rst | 16 | ||||
-rw-r--r-- | __init__.py | 373 | ||||
-rw-r--r-- | py/__init__.py | 371 | ||||
-rw-r--r-- | py/representer.py | 1 | ||||
-rw-r--r-- | py/yaml.py | 145 | ||||
-rw-r--r-- | setup.py | 20 | ||||
-rw-r--r-- | test/lib/canonical.py | 8 | ||||
-rw-r--r-- | test/lib/test_appliance.py | 2 | ||||
-rw-r--r-- | test/lib/test_constructor.py | 4 | ||||
-rw-r--r-- | test/lib/test_input_output.py | 2 | ||||
-rw-r--r-- | test/lib/test_mark.py | 2 | ||||
-rw-r--r-- | test/lib/test_reader.py | 4 | ||||
-rw-r--r-- | test/lib/test_resolver.py | 2 | ||||
-rw-r--r-- | test/lib/test_structure.py | 2 | ||||
-rw-r--r-- | test/lib/test_tokens.py | 2 | ||||
-rw-r--r-- | test/roundtrip.py | 6 | ||||
-rw-r--r-- | test/test_z_data.py | 5 | ||||
-rw-r--r-- | yaml.py | 68 |
18 files changed, 559 insertions, 474 deletions
@@ -4,7 +4,7 @@ ruamel.yaml ``ruamel.yaml`` is a YAML package for Python. It is a derivative of Kirill Simonov's `PyYAML 3.11 <https://bitbucket.org/xi/pyyaml>`_ -which is a YAML1.1 +which supports YAML1.1 Major differences with PyYAML 3.11: @@ -38,7 +38,7 @@ comments, there are no libraries that support round trip updating of such commented files. INI files support comments, and the excellent `ConfigObj -<http://www.voidspace.org.uk/python/configobj.html>` library by Foord +<http://www.voidspace.org.uk/python/configobj.html>`_ library by Foord and Larosa even supports round trip editing with comment preservation, nesting of sections and limited lists (within a value). Retrieval of particular value format is explicit (and extensible). @@ -53,3 +53,15 @@ format. By extending the Python YAML parser to support round trip preservation of comments, it makes YAML a very good choice for configuration files that are human readable and editable while at the same time interpretable and modifiable by a program. + +yaml utlity +=========== + +A utility name ``yaml`` is included and allows for basic operations on files: + +- ``yaml round-trip <file_name>`` for basic roundtrip testing of YAML + files +- ``yaml json <file_name>`` for conversion of JSON file(s) to a single + YAML block style document + +See ``yaml --help`` for more information on the availble commands diff --git a/__init__.py b/__init__.py deleted file mode 100644 index 5170c03..0000000 --- a/__init__.py +++ /dev/null @@ -1,373 +0,0 @@ -# coding: utf-8 - -from __future__ import absolute_import - - -def _convert_version(tup): - """create a PEP 386 pseudo-format conformant string from tuple tup""" - ret_val = str(tup[0]) # first is always digit - next_sep = "." # separator for next extension, can be "" or "." - for x in tup[1:]: - if isinstance(x, int): - ret_val += next_sep + str(x) - next_sep = '.' - continue - first_letter = x[0].lower() - next_sep = '' - if first_letter in 'abcr': - ret_val += 'rc' if first_letter == 'r' else first_letter - elif first_letter in 'pd': - ret_val += '.post' if first_letter == 'p' else '.dev' - return ret_val - - -version_info = (0, 1) -__version__ = _convert_version(version_info) - -del _convert_version - - - -from ruamel.yaml.py.error import * - -from ruamel.yaml.py.tokens import * -from ruamel.yaml.py.events import * -from ruamel.yaml.py.nodes import * - -from ruamel.yaml.py.loader import * -from ruamel.yaml.py.dumper import * -from ruamel.yaml.py.compat import StringIO, BytesIO, with_metaclass, PY3 - -try: - from .cyaml import * - __with_libyaml__ = True -except ImportError: - __with_libyaml__ = False - -import io - - -def scan(stream, Loader=Loader): - """ - Scan a YAML stream and produce scanning tokens. - """ - loader = Loader(stream) - try: - while loader.check_token(): - yield loader.get_token() - finally: - loader.dispose() - - -def parse(stream, Loader=Loader): - """ - Parse a YAML stream and produce parsing events. - """ - loader = Loader(stream) - try: - while loader.check_event(): - yield loader.get_event() - finally: - loader.dispose() - - -def compose(stream, Loader=Loader): - """ - Parse the first YAML document in a stream - and produce the corresponding representation tree. - """ - loader = Loader(stream) - try: - return loader.get_single_node() - finally: - loader.dispose() - - -def compose_all(stream, Loader=Loader): - """ - Parse all YAML documents in a stream - and produce corresponding representation trees. - """ - loader = Loader(stream) - try: - while loader.check_node(): - yield loader.get_node() - finally: - loader.dispose() - - -def load(stream, Loader=Loader): - """ - Parse the first YAML document in a stream - and produce the corresponding Python object. - """ - loader = Loader(stream) - try: - return loader.get_single_data() - finally: - loader.dispose() - - -def load_all(stream, Loader=Loader): - """ - Parse all YAML documents in a stream - and produce corresponding Python objects. - """ - loader = Loader(stream) - try: - while loader.check_data(): - yield loader.get_data() - finally: - loader.dispose() - - -def safe_load(stream): - """ - Parse the first YAML document in a stream - and produce the corresponding Python object. - Resolve only basic YAML tags. - """ - return load(stream, SafeLoader) - - -def safe_load_all(stream): - """ - Parse all YAML documents in a stream - and produce corresponding Python objects. - Resolve only basic YAML tags. - """ - return load_all(stream, SafeLoader) - - -def emit(events, stream=None, Dumper=Dumper, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None): - """ - Emit YAML parsing events into a stream. - If stream is None, return the produced string instead. - """ - getvalue = None - if stream is None: - stream = StringIO() - getvalue = stream.getvalue - dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break) - try: - for event in events: - dumper.emit(event) - finally: - dumper.dispose() - if getvalue: - return getvalue() - -enc = None if PY3 else 'utf-8' - - -def serialize_all(nodes, 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): - """ - Serialize a sequence of representation trees into a YAML stream. - If stream is None, return the produced string instead. - """ - getvalue = None - if stream is None: - if encoding is None: - stream = StringIO() - else: - stream = BytesIO() - getvalue = stream.getvalue - dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break, - encoding=encoding, version=version, tags=tags, - explicit_start=explicit_start, explicit_end=explicit_end) - try: - dumper.open() - for node in nodes: - dumper.serialize(node) - dumper.close() - finally: - dumper.dispose() - if getvalue: - return getvalue() - - -def serialize(node, stream=None, Dumper=Dumper, **kwds): - """ - Serialize a representation tree into a YAML stream. - If stream is None, return the produced string instead. - """ - return serialize_all([node], stream, Dumper=Dumper, **kwds) - - -def dump_all(documents, stream=None, Dumper=Dumper, - default_style=None, default_flow_style=None, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=enc, explicit_start=None, explicit_end=None, - version=None, tags=None): - """ - Serialize a sequence of Python objects into a YAML stream. - If stream is None, return the produced string instead. - """ - getvalue = None - if stream is None: - if encoding is None: - stream = StringIO() - else: - stream = BytesIO() - getvalue = stream.getvalue - dumper = Dumper(stream, default_style=default_style, - default_flow_style=default_flow_style, - canonical=canonical, indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break, - encoding=encoding, version=version, tags=tags, - explicit_start=explicit_start, explicit_end=explicit_end) - try: - dumper.open() - for data in documents: - dumper.represent(data) - dumper.close() - finally: - dumper.dispose() - if getvalue: - return getvalue() - - -def dump(data, stream=None, Dumper=Dumper, **kwds): - """ - Serialize a Python object into a YAML stream. - If stream is None, return the produced string instead. - """ - return dump_all([data], stream, Dumper=Dumper, **kwds) - - -def safe_dump_all(documents, stream=None, **kwds): - """ - Serialize a sequence of Python objects into a YAML stream. - Produce only basic YAML tags. - If stream is None, return the produced string instead. - """ - return dump_all(documents, stream, Dumper=SafeDumper, **kwds) - - -def safe_dump(data, stream=None, **kwds): - """ - Serialize a Python object into a YAML stream. - Produce only basic YAML tags. - If stream is None, return the produced string instead. - """ - return dump_all([data], stream, Dumper=SafeDumper, **kwds) - - -def add_implicit_resolver(tag, regexp, first=None, - Loader=Loader, Dumper=Dumper): - """ - Add an implicit scalar detector. - If an implicit scalar value matches the given regexp, - the corresponding tag is assigned to the scalar. - first is a sequence of possible initial characters or None. - """ - Loader.add_implicit_resolver(tag, regexp, first) - Dumper.add_implicit_resolver(tag, regexp, first) - - -def add_path_resolver(tag, path, kind=None, Loader=Loader, Dumper=Dumper): - """ - Add a path based resolver for the given tag. - A path is a list of keys that forms a path - to a node in the representation tree. - Keys can be string values, integers, or None. - """ - Loader.add_path_resolver(tag, path, kind) - Dumper.add_path_resolver(tag, path, kind) - - -def add_constructor(tag, constructor, Loader=Loader): - """ - Add a constructor for the given tag. - Constructor is a function that accepts a Loader instance - and a node object and produces the corresponding Python object. - """ - Loader.add_constructor(tag, constructor) - - -def add_multi_constructor(tag_prefix, multi_constructor, Loader=Loader): - """ - Add a multi-constructor for the given tag prefix. - Multi-constructor is called for a node if its tag starts with tag_prefix. - Multi-constructor accepts a Loader instance, a tag suffix, - and a node object and produces the corresponding Python object. - """ - Loader.add_multi_constructor(tag_prefix, multi_constructor) - - -def add_representer(data_type, representer, Dumper=Dumper): - """ - Add a representer for the given type. - Representer is a function accepting a Dumper instance - and an instance of the given data type - and producing the corresponding representation node. - """ - Dumper.add_representer(data_type, representer) - - -def add_multi_representer(data_type, multi_representer, Dumper=Dumper): - """ - Add a representer for the given type. - Multi-representer is a function accepting a Dumper instance - and an instance of the given data type or subtype - and producing the corresponding representation node. - """ - Dumper.add_multi_representer(data_type, multi_representer) - - -class YAMLObjectMetaclass(type): - """ - The metaclass for YAMLObject. - """ - def __init__(cls, name, bases, kwds): - super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds) - if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None: - cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) - cls.yaml_dumper.add_representer(cls, cls.to_yaml) - - -class YAMLObject(with_metaclass(YAMLObjectMetaclass)): - """ - An object that can dump itself to a YAML stream - and load itself from a YAML stream. - """ - __slots__ = () # no direct instantiation, so allow immutable subclasses - - yaml_loader = Loader - yaml_dumper = Dumper - - yaml_tag = None - yaml_flow_style = None - - @classmethod - def from_yaml(cls, loader, node): - """ - Convert a representation node to a Python object. - """ - return loader.construct_yaml_object(node, cls) - - @classmethod - def to_yaml(cls, dumper, data): - """ - Convert a Python object to a representation node. - """ - return dumper.represent_yaml_object(cls.yaml_tag, data, cls, - flow_style=cls.yaml_flow_style) - - - -def main(): - # No direct import of yaml in order not to pollute namespace. - # If other utility 'bodies' exist in this directory a module level - # import here, would get you all of its initialisations/imports as well - from yaml import main as util_main - util_main() diff --git a/py/__init__.py b/py/__init__.py index e69de29..23137d3 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -0,0 +1,371 @@ +# coding: utf-8 + +from __future__ import absolute_import + + +def _convert_version(tup): + """create a PEP 386 pseudo-format conformant string from tuple tup""" + ret_val = str(tup[0]) # first is always digit + next_sep = "." # separator for next extension, can be "" or "." + for x in tup[1:]: + if isinstance(x, int): + ret_val += next_sep + str(x) + next_sep = '.' + continue + first_letter = x[0].lower() + next_sep = '' + if first_letter in 'abcr': + ret_val += 'rc' if first_letter == 'r' else first_letter + elif first_letter in 'pd': + ret_val += '.post' if first_letter == 'p' else '.dev' + return ret_val + + +version_info = (0, 2) +__version__ = _convert_version(version_info) + +del _convert_version + + +from ruamel.yaml.error import * + +from ruamel.yaml.tokens import * +from ruamel.yaml.events import * +from ruamel.yaml.nodes import * + +from ruamel.yaml.loader import * +from ruamel.yaml.dumper import * +from ruamel.yaml.compat import StringIO, BytesIO, with_metaclass, PY3 + +try: + from .cyaml import * + __with_libyaml__ = True +except ImportError: + __with_libyaml__ = False + +import io + + +def scan(stream, Loader=Loader): + """ + Scan a YAML stream and produce scanning tokens. + """ + loader = Loader(stream) + try: + while loader.check_token(): + yield loader.get_token() + finally: + loader.dispose() + + +def parse(stream, Loader=Loader): + """ + Parse a YAML stream and produce parsing events. + """ + loader = Loader(stream) + try: + while loader.check_event(): + yield loader.get_event() + finally: + loader.dispose() + + +def compose(stream, Loader=Loader): + """ + Parse the first YAML document in a stream + and produce the corresponding representation tree. + """ + loader = Loader(stream) + try: + return loader.get_single_node() + finally: + loader.dispose() + + +def compose_all(stream, Loader=Loader): + """ + Parse all YAML documents in a stream + and produce corresponding representation trees. + """ + loader = Loader(stream) + try: + while loader.check_node(): + yield loader.get_node() + finally: + loader.dispose() + + +def load(stream, Loader=Loader): + """ + Parse the first YAML document in a stream + and produce the corresponding Python object. + """ + loader = Loader(stream) + try: + return loader.get_single_data() + finally: + loader.dispose() + + +def load_all(stream, Loader=Loader): + """ + Parse all YAML documents in a stream + and produce corresponding Python objects. + """ + loader = Loader(stream) + try: + while loader.check_data(): + yield loader.get_data() + finally: + loader.dispose() + + +def safe_load(stream): + """ + Parse the first YAML document in a stream + and produce the corresponding Python object. + Resolve only basic YAML tags. + """ + return load(stream, SafeLoader) + + +def safe_load_all(stream): + """ + Parse all YAML documents in a stream + and produce corresponding Python objects. + Resolve only basic YAML tags. + """ + return load_all(stream, SafeLoader) + + +def emit(events, stream=None, Dumper=Dumper, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None): + """ + Emit YAML parsing events into a stream. + If stream is None, return the produced string instead. + """ + getvalue = None + if stream is None: + stream = StringIO() + getvalue = stream.getvalue + dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break) + try: + for event in events: + dumper.emit(event) + finally: + dumper.dispose() + if getvalue: + return getvalue() + +enc = None if PY3 else 'utf-8' + + +def serialize_all(nodes, 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): + """ + Serialize a sequence of representation trees into a YAML stream. + If stream is None, return the produced string instead. + """ + getvalue = None + if stream is None: + if encoding is None: + stream = StringIO() + else: + stream = BytesIO() + getvalue = stream.getvalue + dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break, + encoding=encoding, version=version, tags=tags, + explicit_start=explicit_start, explicit_end=explicit_end) + try: + dumper.open() + for node in nodes: + dumper.serialize(node) + dumper.close() + finally: + dumper.dispose() + if getvalue: + return getvalue() + + +def serialize(node, stream=None, Dumper=Dumper, **kwds): + """ + Serialize a representation tree into a YAML stream. + If stream is None, return the produced string instead. + """ + return serialize_all([node], stream, Dumper=Dumper, **kwds) + + +def dump_all(documents, stream=None, Dumper=Dumper, + default_style=None, default_flow_style=None, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=enc, explicit_start=None, explicit_end=None, + version=None, tags=None): + """ + Serialize a sequence of Python objects into a YAML stream. + If stream is None, return the produced string instead. + """ + getvalue = None + if stream is None: + if encoding is None: + stream = StringIO() + else: + stream = BytesIO() + getvalue = stream.getvalue + dumper = Dumper(stream, default_style=default_style, + default_flow_style=default_flow_style, + canonical=canonical, indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break, + encoding=encoding, version=version, tags=tags, + explicit_start=explicit_start, explicit_end=explicit_end) + try: + dumper.open() + for data in documents: + dumper.represent(data) + dumper.close() + finally: + dumper.dispose() + if getvalue: + return getvalue() + + +def dump(data, stream=None, Dumper=Dumper, **kwds): + """ + Serialize a Python object into a YAML stream. + If stream is None, return the produced string instead. + """ + return dump_all([data], stream, Dumper=Dumper, **kwds) + + +def safe_dump_all(documents, stream=None, **kwds): + """ + Serialize a sequence of Python objects into a YAML stream. + Produce only basic YAML tags. + If stream is None, return the produced string instead. + """ + return dump_all(documents, stream, Dumper=SafeDumper, **kwds) + + +def safe_dump(data, stream=None, **kwds): + """ + Serialize a Python object into a YAML stream. + Produce only basic YAML tags. + If stream is None, return the produced string instead. + """ + return dump_all([data], stream, Dumper=SafeDumper, **kwds) + + +def add_implicit_resolver(tag, regexp, first=None, + Loader=Loader, Dumper=Dumper): + """ + Add an implicit scalar detector. + If an implicit scalar value matches the given regexp, + the corresponding tag is assigned to the scalar. + first is a sequence of possible initial characters or None. + """ + Loader.add_implicit_resolver(tag, regexp, first) + Dumper.add_implicit_resolver(tag, regexp, first) + + +def add_path_resolver(tag, path, kind=None, Loader=Loader, Dumper=Dumper): + """ + Add a path based resolver for the given tag. + A path is a list of keys that forms a path + to a node in the representation tree. + Keys can be string values, integers, or None. + """ + Loader.add_path_resolver(tag, path, kind) + Dumper.add_path_resolver(tag, path, kind) + + +def add_constructor(tag, constructor, Loader=Loader): + """ + Add a constructor for the given tag. + Constructor is a function that accepts a Loader instance + and a node object and produces the corresponding Python object. + """ + Loader.add_constructor(tag, constructor) + + +def add_multi_constructor(tag_prefix, multi_constructor, Loader=Loader): + """ + Add a multi-constructor for the given tag prefix. + Multi-constructor is called for a node if its tag starts with tag_prefix. + Multi-constructor accepts a Loader instance, a tag suffix, + and a node object and produces the corresponding Python object. + """ + Loader.add_multi_constructor(tag_prefix, multi_constructor) + + +def add_representer(data_type, representer, Dumper=Dumper): + """ + Add a representer for the given type. + Representer is a function accepting a Dumper instance + and an instance of the given data type + and producing the corresponding representation node. + """ + Dumper.add_representer(data_type, representer) + + +def add_multi_representer(data_type, multi_representer, Dumper=Dumper): + """ + Add a representer for the given type. + Multi-representer is a function accepting a Dumper instance + and an instance of the given data type or subtype + and producing the corresponding representation node. + """ + Dumper.add_multi_representer(data_type, multi_representer) + + +class YAMLObjectMetaclass(type): + """ + The metaclass for YAMLObject. + """ + def __init__(cls, name, bases, kwds): + super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds) + if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None: + cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) + cls.yaml_dumper.add_representer(cls, cls.to_yaml) + + +class YAMLObject(with_metaclass(YAMLObjectMetaclass)): + """ + An object that can dump itself to a YAML stream + and load itself from a YAML stream. + """ + __slots__ = () # no direct instantiation, so allow immutable subclasses + + yaml_loader = Loader + yaml_dumper = Dumper + + yaml_tag = None + yaml_flow_style = None + + @classmethod + def from_yaml(cls, loader, node): + """ + Convert a representation node to a Python object. + """ + return loader.construct_yaml_object(node, cls) + + @classmethod + def to_yaml(cls, dumper, data): + """ + Convert a Python object to a representation node. + """ + return dumper.represent_yaml_object(cls.yaml_tag, data, cls, + flow_style=cls.yaml_flow_style) + + +def main(): + # No direct import of yaml in order not to pollute namespace. + # If other utility 'bodies' exist in this directory a module level + # import here, would get you all of its initialisations/imports as well + from ruamel.yaml.yaml import main as util_main + util_main() diff --git a/py/representer.py b/py/representer.py index a36256d..a30c540 100644 --- a/py/representer.py +++ b/py/representer.py @@ -733,4 +733,3 @@ RoundTripRepresenter.add_representer(CommentedMap, RoundTripRepresenter.add_representer(set, RoundTripRepresenter.represent_set) - diff --git a/py/yaml.py b/py/yaml.py new file mode 100644 index 0000000..71178c2 --- /dev/null +++ b/py/yaml.py @@ -0,0 +1,145 @@ +# coding: utf-8 + +""" +this is the source for the yaml utility +""" + +from __future__ import print_function + +import sys +import os +import io + +from ruamel.std.argparse import ProgramBase, option, sub_parser, version, \ + CountAction, SmartFormatter +# from ruamel.appconfig import AppConfig +from . import __version__ + +import ruamel.yaml + + +class YAML: + def __init__(self, args, config): + self._args = args + self._config = config + + def from_json(self): + # use roundtrip to preserver order + errors = 0 + docs = [] + for file_name in self._args.file: + inp = open(file_name).read() + loader = ruamel.yaml.RoundTripLoader + docs.append(ruamel.yaml.load(inp, loader)) + stream = io.StringIO() + dumper = ruamel.yaml.RoundTripDumper + print(ruamel.yaml.dump_all(docs, Dumper=dumper)) + return 1 if errors else 0 + + def round_trip(self): + errors = 0 + warnings = 0 + for file_name in self._args.file: + inp = open(file_name).read() + outp = self.round_trip_single(inp) + if inp == outp: + if self._args.verbose > 0: + print(u"{0}: ok".format(file_name)) + continue + warnings += 1 + stabelize = [] + if inp.split() != outp.split(): + errors += 1 + stabelize.append(u"drops info on round trip") + else: + if self.round_trip_single(outp) == outp: + stabelize.append(u"stabelizes on second round trip") + else: + errors += 1 + ncoutp = self.round_trip_single(inp, drop_comment=True) + if self.round_trip_single(ncoutp, drop_comment=True) == ncoutp: + stabelize.append(u"ok without comments") + print("{0}:\n {1}".format(file_name, u', '.join(stabelize))) + self.diff(inp, outp, file_name) + return 2 if errors > 0 else 1 if warnings > 0 else 0 + + def round_trip_single(self, inp, drop_comment=False): + loader = ruamel.yaml.SafeLoader if drop_comment else \ + ruamel.yaml.RoundTripLoader + code = ruamel.yaml.load(inp, loader) + stream = io.StringIO() + dumper = ruamel.yaml.SafeDumper if drop_comment else \ + ruamel.yaml.RoundTripDumper + return ruamel.yaml.dump(code, Dumper=dumper) + + def diff(self, inp, outp, file_name): + import difflib + inl = inp.splitlines(True) # True for keepends + outl = outp.splitlines(True) + diff = difflib.unified_diff(inl, outl, file_name, 'round trip YAML') + sys.stdout.writelines(diff) + + +def to_stdout(*args): + sys.stdout.write(' '.join(args)) + + +class YAML_Cmd(ProgramBase): + def __init__(self): + super(YAML_Cmd, self).__init__( + formatter_class=SmartFormatter, + aliases=True, + ) + self._config = None + + # you can put these on __init__, but subclassing YAML_Cmd + # will cause that to break + @option('--verbose', '-v', + help='increase verbosity level', action=CountAction, + const=1, nargs=0, default=0, global_option=True) + @version('version: ' + __version__) + def _pb_init(self): + # special name for which attribs are included in help + pass + + def run(self): + yaml = YAML(self._args, self._config) + if self._args.func: + return self._args.func(yaml) + + def parse_args(self): + # self._config = AppConfig( + # 'yaml', + # filename=AppConfig.check, + # parser=self._parser, # sets --config option + # warning=to_stdout, + # add_save=False, # add a --save-defaults (to config) option + # ) + # self._config._file_name can be handed to objects that need + # to get other information from the configuration directory + # self._config.set_defaults() + self._parse_args() + + @sub_parser( + aliases=['round-trip'], + help='test round trip on YAML data', + description='test round trip on YAML data', + ) + @option('file', nargs='+') + def rt(self, yaml): + return yaml.round_trip() + + @sub_parser( + aliases=['from-json'], + help='convert json to block YAML', + description='convert json to block YAML', + ) + @option('file', nargs='+') + def json(self, yaml): + return yaml.from_json() + + +def main(): + n = YAML_Cmd() + n.parse_args() + sys.exit(n.run()) @@ -18,7 +18,7 @@ exclude_files = [ def get_version(): v_i = 'version_info = ' - for line in open('__init__.py'): + for line in open('py/__init__.py'): if not line.startswith(v_i): continue s_e = line[len(v_i):].strip()[1:-1].split(', ') @@ -109,14 +109,16 @@ class MyInstallLib(install_lib.install_lib): def main(): install_requires = [ + "ruamel.std.argparse", ] # use fast ordereddict for !!omap - install_requires = ['ruamel.ordereddict'] \ - if sys.version_info[0] == 2 else [] + if sys.version_info[0] == 2: + install_requires.extend(['ruamel.ordereddict']) # if sys.version_info < (3, 4): # install_requires.append("") - packages = [full_package_name] + [(full_package_name + '.' + x) for x - in find_packages(exclude=['tests'])] + packages = [full_package_name] + [ + (full_package_name + '.' + x) + for x in find_packages('py', exclude=['tests'])] setup( name=full_package_name, version=version_str, @@ -128,7 +130,7 @@ def main(): author='Anthon van der Neut', author_email='a.van.der.neut@ruamel.eu', license="MIT license", - package_dir={full_package_name: '.'}, + package_dir={full_package_name: 'py'}, namespace_packages=[name_space], packages=packages, entry_points=mk_entry_points(full_package_name), @@ -143,10 +145,10 @@ def main(): ) -def mk_entry_points(package_name): - script_name = package_name.replace('.', '_') +def mk_entry_points(full_package_name): + script_name = full_package_name.rsplit('.', 1)[-1] return {'console_scripts': [ - '{0} = {1}:main'.format(script_name, package_name), + '{0} = {1}:main'.format(script_name, full_package_name), ]} if __name__ == '__main__': diff --git a/test/lib/canonical.py b/test/lib/canonical.py index 9932d45..c273e01 100644 --- a/test/lib/canonical.py +++ b/test/lib/canonical.py @@ -1,9 +1,9 @@ import ruamel.yaml -from ruamel.yaml.py.composer import Composer -from ruamel.yaml.py.constructor import Constructor -from ruamel.yaml.py.resolver import Resolver -from ruamel.yaml.py.compat import unichr, PY3 +from ruamel.yaml.composer import Composer +from ruamel.yaml.constructor import Constructor +from ruamel.yaml.resolver import Resolver +from ruamel.yaml.compat import unichr, PY3 class CanonicalError(ruamel.yaml.YAMLError): pass diff --git a/test/lib/test_appliance.py b/test/lib/test_appliance.py index b6896f7..03ee6d7 100644 --- a/test/lib/test_appliance.py +++ b/test/lib/test_appliance.py @@ -7,7 +7,7 @@ import types import traceback import pprint import argparse -from ruamel.yaml.py.compat import PY3 +from ruamel.yaml.compat import PY3 # DATA = 'tests/data' # determine the position of data dynamically relative to program diff --git a/test/lib/test_constructor.py b/test/lib/test_constructor.py index 593805b..544a80e 100644 --- a/test/lib/test_constructor.py +++ b/test/lib/test_constructor.py @@ -3,14 +3,14 @@ from __future__ import print_function import ruamel.yaml import pprint -from ruamel.yaml.py.compat import PY2, PY3 +from ruamel.yaml.compat import PY2, PY3 import datetime try: set except NameError: from sets import Set as set -import ruamel.yaml.py.tokens +import ruamel.yaml.tokens def execute(code): global value diff --git a/test/lib/test_input_output.py b/test/lib/test_input_output.py index cbe57d5..7d103dc 100644 --- a/test/lib/test_input_output.py +++ b/test/lib/test_input_output.py @@ -3,7 +3,7 @@ from __future__ import print_function import ruamel.yaml as yaml import codecs, tempfile, os, os.path -from ruamel.yaml.py.compat import PY2, PY3, StringIO, BytesIO +from ruamel.yaml.compat import PY2, PY3, StringIO, BytesIO if PY2: def _unicode_open(file, encoding, errors='strict'): diff --git a/test/lib/test_mark.py b/test/lib/test_mark.py index 7935965..0574f20 100644 --- a/test/lib/test_mark.py +++ b/test/lib/test_mark.py @@ -2,7 +2,7 @@ from __future__ import absolute_import from __future__ import print_function import ruamel.yaml as yaml -from ruamel.yaml.py.compat import text_type, PY3 +from ruamel.yaml.compat import text_type, PY3 def test_marks(marks_filename, verbose=False): inputs = open(marks_filename, 'r' if PY3 else 'rb').read( diff --git a/test/lib/test_reader.py b/test/lib/test_reader.py index 484a7ce..157c652 100644 --- a/test/lib/test_reader.py +++ b/test/lib/test_reader.py @@ -4,8 +4,8 @@ from __future__ import print_function import codecs import io -from ruamel.yaml.py.compat import PY2 -import ruamel.yaml.py.reader +from ruamel.yaml.compat import PY2 +import ruamel.yaml.reader def _run_reader(data, verbose): try: diff --git a/test/lib/test_resolver.py b/test/lib/test_resolver.py index 371f1b8..bc3928f 100644 --- a/test/lib/test_resolver.py +++ b/test/lib/test_resolver.py @@ -3,7 +3,7 @@ from __future__ import print_function import ruamel.yaml as yaml import pprint -from ruamel.yaml.py.compat import PY3 +from ruamel.yaml.compat import PY3 def test_implicit_resolver(data_filename, detect_filename, verbose=False): correct_tag = None diff --git a/test/lib/test_structure.py b/test/lib/test_structure.py index f6a29aa..353d432 100644 --- a/test/lib/test_structure.py +++ b/test/lib/test_structure.py @@ -4,7 +4,7 @@ from __future__ import print_function import ruamel.yaml as yaml import canonical import pprint -from ruamel.yaml.py.compat import text_type, PY3 +from ruamel.yaml.compat import text_type, PY3 def _convert_structure(loader): if loader.check_event(yaml.ScalarEvent): diff --git a/test/lib/test_tokens.py b/test/lib/test_tokens.py index 6ba3a86..23c9380 100644 --- a/test/lib/test_tokens.py +++ b/test/lib/test_tokens.py @@ -3,7 +3,7 @@ from __future__ import print_function import ruamel.yaml as yaml import pprint -from ruamel.yaml.py.compat import PY3 +from ruamel.yaml.compat import PY3 # Tokens mnemonic: # directive: % diff --git a/test/roundtrip.py b/test/roundtrip.py index b5dadda..374bff3 100644 --- a/test/roundtrip.py +++ b/test/roundtrip.py @@ -10,8 +10,6 @@ except ImportError: from io import StringIO import ruamel.yaml -from ruamel.yaml import RoundTripLoader -from ruamel.yaml import RoundTripDumper def dedent(data): @@ -28,12 +26,12 @@ def dedent(data): def round_trip_load(dinp): - return ruamel.yaml.load(dinp, RoundTripLoader) + return ruamel.yaml.load(dinp, ruamel.yaml.RoundTripLoader) def round_trip_dump(data): stream = StringIO() - dumper = RoundTripDumper + dumper = ruamel.yaml.RoundTripDumper return ruamel.yaml.dump(data, default_flow_style=False, Dumper=dumper) diff --git a/test/test_z_data.py b/test/test_z_data.py index c221c76..19d454c 100644 --- a/test/test_z_data.py +++ b/test/test_z_data.py @@ -20,12 +20,11 @@ def test_data(): test_appliance.run(collections, args) -@pytest.mark.skipif(not ruamel.yaml.__with_libyaml__, - reason="no libyaml") +@pytest.mark.skipif(not ruamel.yaml.__with_libyaml__, + reason="no libyaml") def test_data_ext(): collections = [] if ruamel.yaml.__with_libyaml__: import test_yaml_ext collections.append(test_yaml_ext) test_appliance.run(collections, args) - diff --git a/yaml.py b/yaml.py deleted file mode 100644 index b4b36a6..0000000 --- a/yaml.py +++ /dev/null @@ -1,68 +0,0 @@ -# coding: utf-8 - -from __future__ import print_function - -import sys -import os - -from ruamel.std.argparse import ProgramBase, option, sub_parser, version, \ - CountAction, SmartFormatter -from ruamel.appconfig import AppConfig -from . import __version__ - - -class YAML: - def __init__(self, args, config): - self._args = args - self._config = config - - -def to_stdout(*args): - sys.stdout.write(' '.join(args)) - - -class YAML_Cmd(ProgramBase): - def __init__(self): - super(YAML_Cmd, self).__init__( - formatter_class=SmartFormatter - ) - - # you can put these on __init__, but subclassing YAML_Cmd - # will cause that to break - @option('--verbose', '-v', - help='increase verbosity level', action=CountAction, - const=1, nargs=0, default=0, global_option=True) - @version('version: ' + __version__) - def _pb_init(self): - # special name for which attribs are included in help - pass - - def run(self): - yaml = YAML(self._args, self._config) - # if self._args.func: - # return self._args.func() - - def parse_args(self): - #self._config = AppConfig( - # 'yaml', - # filename=AppConfig.check, - # parser=self._parser, # sets --config option - # warning=to_stdout, - # add_save=False, # add a --save-defaults (to config) option - #) - # self._config._file_name can be handed to objects that need - # to get other information from the configuration directory - #self._config.set_defaults() - self._parse_args() - - # @sub_parser(help='some command specific help for tmux') - # @option('--session-name', default='abc') - # def tmux(self): - # from plumbum.cmd import tmux - # from plumbum.commands.processes import ProcessExecutionError - - -def main(): - n = YAML_Cmd() - n.parse_args() - n.run() |