From 4014dbfe0faad96555e738060f1128fb445f4de7 Mon Sep 17 00:00:00 2001
From: kaliv0
Date: Sat, 14 Dec 2024 15:59:16 +0200
Subject: [PATCH 1/3] added clear_aliases() and more test cases
---
aldict/alias_dict.py | 3 ++
tests/test_alias_dict.py | 59 ++++++++++++++++++++++++++++++++++++----
2 files changed, 57 insertions(+), 5 deletions(-)
diff --git a/aldict/alias_dict.py b/aldict/alias_dict.py
index e22fc81..a9c5700 100644
--- a/aldict/alias_dict.py
+++ b/aldict/alias_dict.py
@@ -25,6 +25,9 @@ def remove_alias(self, *aliases):
except KeyError:
raise AliasError(alias)
+ def clear_aliases(self):
+ self._alias_dict.clear()
+
def aliases(self):
return self._alias_dict.keys()
diff --git a/tests/test_alias_dict.py b/tests/test_alias_dict.py
index a9ca699..d5aa87c 100644
--- a/tests/test_alias_dict.py
+++ b/tests/test_alias_dict.py
@@ -136,13 +136,12 @@ def test_get(alias_dict):
assert alias_dict.get(".foo") is None
-def test_pop(alias_dict):
+def test_pop_alias_doesnt_remove_key(alias_dict):
assert alias_dict.pop(".yml") == {
"callable": "safe_load",
"import_mod": "yaml",
"read_mode": "r",
}
- # removing the alias doesn't remove the key
assert ".yaml" in alias_dict
@@ -175,15 +174,65 @@ def test_repr(alias_dict):
def test_eq():
- ad_1 = AliasDict({"a": 1, "b": 2})
+ ad_0 = {"a": 1, "b": 2}
+ ad_1 = AliasDict(ad_0)
ad_1.add_alias("a", "aa", "aaa")
- ad_2 = AliasDict({"a": 1, "b": 2})
+ ad_2 = AliasDict(ad_0)
ad_2.add_alias("a", "aa", "aaa")
- ad_3 = AliasDict({"a": 1, "b": 2})
+ ad_3 = AliasDict(ad_0)
ad_3.add_alias("a", "abc")
assert ad_1 == ad_2
assert ad_1 != ad_3
assert ad_2 != ad_3
+
+
+def test_dict_len_doesnt_include_aliases(alias_dict):
+ assert list(alias_dict.keys()) == [".json", ".yaml", ".toml", ".yml"]
+ assert len(alias_dict) == 3
+
+
+def test_popitem(alias_dict):
+ # pops first item -> MutableMapping.popitem()
+ assert alias_dict.popitem() == (
+ ".json",
+ {"callable": "load", "import_mod": "json", "read_mode": "r"},
+ )
+ assert alias_dict.popitem() == (
+ ".yaml",
+ {"callable": "safe_load", "import_mod": "yaml", "read_mode": "r"},
+ )
+ assert list(alias_dict.aliased_keys()) == []
+ assert list(alias_dict.keys()) == [".toml"]
+
+
+def test_clear(alias_dict):
+ alias_dict.clear()
+ assert len(alias_dict.items()) == 0
+
+
+def test_clear_aliases(alias_dict):
+ alias_dict.clear_aliases()
+ assert len(alias_dict.aliases()) == 0
+ assert list(alias_dict.items()) == [
+ (".json", {"callable": "load", "import_mod": "json", "read_mode": "r"}),
+ (".yaml", {"callable": "safe_load", "import_mod": "yaml", "read_mode": "r"}),
+ (".toml", {"callable": "load", "import_mod": "tomli", "read_mode": "r"}),
+ ]
+
+
+def test_setdefault():
+ ad = AliasDict({"a": 1, "b": 2})
+ ad.setdefault("foo", "bar")
+ ad.add_alias("foo", "fizz")
+ assert ad["foo"] == "bar"
+ assert ad["fizz"] == "bar"
+
+
+def test_update_modifies_aliases():
+ ad = AliasDict({"a": 1, "b": 2})
+ ad.add_alias("a", "aa", "aaa")
+ ad.update(**{"a": 40, "y": 50})
+ assert list(ad.items()) == [("a", 40), ("b", 2), ("y", 50), ("aa", 40), ("aaa", 40)]
From ec9b0ddbc4ea21e4952f96dd1d02fabc38436db3 Mon Sep 17 00:00:00 2001
From: kaliv0
Date: Sat, 14 Dec 2024 16:05:28 +0200
Subject: [PATCH 2/3] tested setdefault on existing key
---
tests/test_alias_dict.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/tests/test_alias_dict.py b/tests/test_alias_dict.py
index d5aa87c..765ce8e 100644
--- a/tests/test_alias_dict.py
+++ b/tests/test_alias_dict.py
@@ -204,7 +204,7 @@ def test_popitem(alias_dict):
".yaml",
{"callable": "safe_load", "import_mod": "yaml", "read_mode": "r"},
)
- assert list(alias_dict.aliased_keys()) == []
+ assert len(alias_dict.aliased_keys()) == 0
assert list(alias_dict.keys()) == [".toml"]
@@ -231,6 +231,14 @@ def test_setdefault():
assert ad["fizz"] == "bar"
+def test_setdefault_on_existing_aliased_key():
+ ad = AliasDict({"a": 1, "b": 2})
+ ad.setdefault("a", 42)
+ ad.add_alias("a", "aa")
+ assert ad["a"] == 1
+ assert ad["aa"] == 1
+
+
def test_update_modifies_aliases():
ad = AliasDict({"a": 1, "b": 2})
ad.add_alias("a", "aa", "aaa")
From 51408bddb320be84aca509bcc20261260b244f1d Mon Sep 17 00:00:00 2001
From: kaliv0
Date: Sun, 15 Dec 2024 12:47:45 +0200
Subject: [PATCH 3/3] expanded readme
---
README.md | 78 ++++++++++++++++++++++++++++++++++++++--
aldict/alias_dict.py | 11 +++---
pyproject.toml | 2 +-
tests/test_alias_dict.py | 4 +--
4 files changed, 86 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index 987a8bd..7f3afd8 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,6 @@
---
-
# Aldict
[](https://github.com/kaliv0/aldict/actions/workflows/ci.yml)
@@ -11,4 +10,79 @@
[](https://pypi.org/project/aldict/)
[](https://github.com/kaliv0/aldict/blob/main/LICENSE)
-Multi-key dictionary, supports adding and manipulating key-aliases pointing to shared values
\ No newline at end of file
+Multi-key dictionary, supports adding and manipulating key-aliases pointing to shared values
+
+---
+## How to use
+
+- add_alias
+
(pass key as first parameter and alias(es) as variadic params)
+```python
+ad = AliasDict({"a": 1, "b": 2})
+ad.add_alias("a", "aa")
+ad.add_alias("b", "bb", "Bbb")
+assert ad["a"] == ad["aa"] == 1
+assert ad["b"] == ad["bb"] == ad["Bbb"] == 2
+```
+- remove_alias
+
(pass alias(es) to be removed as variadic parameters)
+```python
+ad.remove_alias("aa")
+ad.remove_alias("bb", "Bbb")
+assert len(ad.aliases()) == 0
+```
+- clear_aliases
+
(remove all aliases at once)
+```python
+ad.clear_aliases()
+assert len(ad.aliases()) == 0
+```
+- update alias
+
(point alias to different key)
+```python
+ad = AliasDict({"a": 1, "b": 2})
+ad.add_alias("a", "ab")
+assert list(ad.items()) == [('a', 1), ('b', 2), ('ab', 1)]
+
+ad.add_alias("b", "ab")
+assert list(ad.items()) == [('a', 1), ('b', 2), ('ab', 2)]
+```
+- read all aliases
+```python
+ad = AliasDict({"a": 1, "b": 2})
+ad.add_alias("a", "aa")
+ad.add_alias("b", "bb", "B")
+ad.add_alias("a", "ab", "A")
+assert list(ad.aliases()) == ['aa', 'bb', 'B', 'ab', 'A']
+```
+- aliased_keys
+
(read keys with corresponding alias(es))
+```python
+assert dict(ad.aliased_keys()) == {'a': ['aa', 'ab', 'A'], 'b': ['bb', 'B']}
+```
+- read dictviews
+
(dict.keys() and dict.items() include aliased versions)
+```python
+ad = AliasDict({"x": 10, "y": 20})
+ad.add_alias("x", "Xx")
+ad.add_alias("y", "Yy", "xyz")
+
+ad.keys()
+ad.values()
+ad.items()
+```
+```shell
+dict_keys(['x', 'y', 'Xx', 'Yy', 'xyz'])
+dict_values([10, 20])
+dict_items([('x', 10), ('y', 20), ('Xx', 10), ('Yy', 20), ('xyz', 20)])
+```
+- remove key and aliases
+```python
+ad.pop("y")
+assert list(ad.items()) == [('x', 10), ('Xx', 10)]
+```
+- origin_keys
+
(get original keys only)
+```python
+assert list(ad.origin_keys()) == ['x', 'y']
+```
\ No newline at end of file
diff --git a/aldict/alias_dict.py b/aldict/alias_dict.py
index a9c5700..1988f8d 100644
--- a/aldict/alias_dict.py
+++ b/aldict/alias_dict.py
@@ -22,8 +22,8 @@ def remove_alias(self, *aliases):
for alias in aliases:
try:
self._alias_dict.__delitem__(alias)
- except KeyError:
- raise AliasError(alias)
+ except KeyError as e:
+ raise AliasError(alias) from e
def clear_aliases(self):
self._alias_dict.clear()
@@ -52,8 +52,8 @@ def items(self):
def __missing__(self, key):
try:
return super().__getitem__(self._alias_dict[key])
- except AttributeError:
- raise KeyError(key)
+ except AttributeError as e:
+ raise KeyError(key) from e
def __setitem__(self, key, value):
try:
@@ -77,6 +77,9 @@ def __iter__(self):
for item in self.keys():
yield item
+ def __len__(self):
+ return len(self.keys())
+
def __repr__(self):
return f"AliasDict({self.items()})"
diff --git a/pyproject.toml b/pyproject.toml
index 6d63010..fd8d19d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "aldict"
-version = "0.1.0"
+version = "1.0.0"
readme = "README.md"
authors = [{ name = "Kaloyan Ivanov", email = "kaloyan.ivanov88@gmail.com" }]
description = "Multi-key dictionary, supports adding and manipulating key-aliases pointing to shared values"
diff --git a/tests/test_alias_dict.py b/tests/test_alias_dict.py
index 765ce8e..f9b9af8 100644
--- a/tests/test_alias_dict.py
+++ b/tests/test_alias_dict.py
@@ -189,9 +189,9 @@ def test_eq():
assert ad_2 != ad_3
-def test_dict_len_doesnt_include_aliases(alias_dict):
+def test_dict_len_includes_aliases(alias_dict):
assert list(alias_dict.keys()) == [".json", ".yaml", ".toml", ".yml"]
- assert len(alias_dict) == 3
+ assert len(alias_dict) == 4
def test_popitem(alias_dict):