diff --git a/.travis.yml b/.travis.yml index 348c753..8d84153 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,10 @@ sudo: false python: - "2.7" - - "3.4" - "3.5" - "3.6" - - "3.7-dev" + - "3.7" + - "3.8" - "nightly" - "pypy" - "pypy3" @@ -16,7 +16,7 @@ env: - PYYAML_VERSION="3.13" # - PYYAML_VERSION="4.1" # this was pulled from the index (!) ..wtf, Ingy? - PYYAML_VERSION="4.2b4" - - PYYAML_VERSION="5.1" + - PYYAML_VERSION="5.3" matrix: fast_finish: true diff --git a/oyaml.py b/oyaml.py index 0d88865..9de26fa 100644 --- a/oyaml.py +++ b/oyaml.py @@ -25,29 +25,29 @@ def map_constructor(loader, node): raise -if pyyaml.safe_dump is pyyaml.dump: - # PyYAML v4.x - SafeDumper = pyyaml.dumper.Dumper - DangerDumper = pyyaml.dumper.DangerDumper +_loaders = [getattr(pyyaml.loader, x) for x in pyyaml.loader.__all__] +_dumpers = [getattr(pyyaml.dumper, x) for x in pyyaml.dumper.__all__] +try: + _cyaml = pyyaml.cyaml.__all__ +except AttributeError: + pass else: - SafeDumper = pyyaml.dumper.SafeDumper - DangerDumper = pyyaml.dumper.Dumper - -pyyaml.add_representer(dict, map_representer, Dumper=SafeDumper) -pyyaml.add_representer(OrderedDict, map_representer, Dumper=SafeDumper) -pyyaml.add_representer(dict, map_representer, Dumper=DangerDumper) -pyyaml.add_representer(OrderedDict, map_representer, Dumper=DangerDumper) + _loaders += [getattr(pyyaml.cyaml, x) for x in _cyaml if x.endswith("Loader")] + _dumpers += [getattr(pyyaml.cyaml, x) for x in _cyaml if x.endswith("Dumper")] +Dumper = None +for Dumper in _dumpers: + pyyaml.add_representer(dict, map_representer, Dumper=Dumper) + pyyaml.add_representer(OrderedDict, map_representer, Dumper=Dumper) Loader = None if not _std_dict_is_order_preserving: - for loader_name in pyyaml.loader.__all__: - Loader = getattr(pyyaml.loader, loader_name) + for Loader in _loaders: pyyaml.add_constructor("tag:yaml.org,2002:map", map_constructor, Loader=Loader) # Merge PyYAML namespace into ours. # This allows users a drop-in replacement: # import oyaml as yaml -del map_constructor, map_representer, SafeDumper, DangerDumper, Loader +del map_constructor, map_representer, Loader, Dumper from yaml import * diff --git a/setup.py b/setup.py index a09cccf..07dcb63 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="oyaml", - version="0.9", + version="1.0", description="Ordered YAML: drop-in replacement for PyYAML which preserves dict ordering", long_description=open("README.rst").read(), author="Wim Glenn", diff --git a/test_oyaml.py b/test_oyaml.py index bc6136e..8058c22 100644 --- a/test_oyaml.py +++ b/test_oyaml.py @@ -192,3 +192,17 @@ def test_merge(): def test_unhashable_error_context(): with pytest.raises(ConstructorError, match=r".*line.*column.*"): yaml.safe_load("{foo: bar}: baz") + + +@pytest.mark.skipif(not hasattr(yaml, "CSafeLoader"), reason="requires cyaml loaders") +def test_explicit_loader(): + data = yaml.load("{x: 1, z: 3, y: 2}", Loader=yaml.CSafeLoader) + assert data == {"x": 1, "z": 3, "y": 2} + assert list(data) == ["x", "z", "y"] + + +@pytest.mark.skipif(not hasattr(yaml, "CSafeDumper"), reason="requires cyaml dumpers") +def test_explicit_dumper(): + data = OrderedDict([("x", 1), ("z", 3), ("y", 2)]) + text = yaml.dump(data, Dumper=yaml.CSafeDumper, default_flow_style=None) + assert text == "{x: 1, z: 3, y: 2}\n"