Procházet zdrojové kódy

added ioex.dict_collapse

Fabian Peter Hammerle před 8 roky
rodič
revize
57a4ed55c5
3 změnil soubory, kde provedl 48 přidání a 2 odebrání
  1. 16 0
      ioex/__init__.py
  2. 2 2
      setup.py
  3. 30 0
      tests/test_dict_collapse.py

+ 16 - 0
ioex/__init__.py

@@ -126,3 +126,19 @@ class AutoDict(dict):
     @classmethod
     def register_yaml_representer(cls, dumper):
         dumper.add_representer(cls, cls.to_yaml)
+
+
+def dict_collapse(dict_src, key_repl):
+    def single_not_none(sub_dict):
+        not_none = [v for v in sub_dict.values() if v is not None]
+        if len(not_none) == 0:
+            return None
+        elif len(not_none) == 1:
+            return not_none[0]
+        else:
+            raise ValueError(sub_dict)
+
+    sub_dicts = AutoDict()
+    for key in dict_src:
+        sub_dicts[key_repl(key)][key] = dict_src[key]
+    return {key: single_not_none(sub) for key, sub in sub_dicts.items()}

+ 2 - 2
setup.py

@@ -5,12 +5,12 @@ import glob
 setup(
     name = 'ioex',
     packages = ['ioex'],
-    version = '0.12.0',
+    version = '0.13.0',
     description = 'extension for python\'s build-in input / output interface',
     author = 'Fabian Peter Hammerle',
     author_email = 'fabian.hammerle@gmail.com',
     url = 'https://github.com/fphammerle/ioex',
-    download_url = 'https://github.com/fphammerle/ioex/tarball/0.12.0',
+    download_url = 'https://github.com/fphammerle/ioex/tarball/0.13.0',
     keywords = [],
     classifiers = [],
     scripts = glob.glob('scripts/*'),

+ 30 - 0
tests/test_dict_collapse.py

@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+import pytest
+
+from ioex import dict_collapse
+
+
+@pytest.mark.parametrize(('src', 'key_repl', 'expected'), [
+    [{'a': 'a'}, lambda k: k.upper(), {'A': 'a'}],
+    [{'a1': 'a', 'a2': None}, lambda k: k[0], {'a': 'a'}],
+    [{'a1': None, 'a2': 'a'}, lambda k: k[0], {'a': 'a'}],
+    [{'a1': None, 'a2': False}, lambda k: k[0], {'a': False}],
+    [{'a1': None, 'a2': (None,)}, lambda k: k[0], {'a': (None,)}],
+    [{'1': 'a', 1.0: 'b'}, lambda k: k, {'1': 'a', 1.0: 'b'}],
+    [{'1': None, 1.0: 'b'}, lambda k: int(k), {1: 'b'}],
+])
+def test_collapse(src, key_repl, expected):
+    assert expected == dict_collapse(src, key_repl)
+
+
+@pytest.mark.parametrize(('src', 'key_repl'), [
+    [{'a1': 1, 'a2': 2}, lambda k: k[0]],
+    [{'a1': None, 'a2': 2, 'a3': 3}, lambda k: k[0]],
+    [{'a1': True, 'a2': False}, lambda k: k[0]],
+    [{'a1': True, 'a2': (None,)}, lambda k: k[0]],
+    [{'a1': True, 'a2': []}, lambda k: k[0]],
+    [{'1': 'a', 1.0: 'b'}, lambda k: int(k)],
+])
+def test_collapse_fail(src, key_repl):
+    with pytest.raises(ValueError):
+        dict_collapse(src, key_repl)